0
printf(&unix["\021C%set"],(unix)["Chb"]+"Trick"-0X67);

It gives output as "Cricket". But I am not able to understand why? http://ideone.com/fTEAHG

Vivek Goel
  • 22,942
  • 29
  • 114
  • 186

2 Answers2

4

unix is a predefined macro indicating it's a Unix-like system.

In C, index[array] is identical to array[index]. As explained by MSDN:

Usually, the value represented by postfix-expression is a pointer value, such as an array identifier, and expression is an integral value (including enumerated types). However, all that is required syntactically is that one of the expressions be of pointer type and the other be of integral type. Thus the integral value could be in the postfix-expression position and the pointer value could be in the brackets in the expression or subscript position.

So

printf(&unix["\021C%set"],(unix)["Chb"]+"Trick"-0X67);

translates to

printf(&"(\021C%set"[1]),"Chb"[1]+"Trick"-0X67);

&("\021C%set"[1]) takes the address of the first element of "\021C%set", which is equivalent to taking the address of "C%set" (due to C pointer arithmetic). Simplify that, and rearrange some operands:

printf("C%set","Trick"+"Chb"[1]-0X67);

"Chb"[1] is 'h', which is ASCII value 0x68, so "Chb"[1]-0X67 is 1, and "Trick"+1 is "rick" (due to C pointer arithmetic). So the code simplifies further to

printf("C%set","rick");

which prints "Cricket."

Josh Kelley
  • 56,064
  • 19
  • 146
  • 246
  • Can you clarify why `&("\021C%set"[1])` is the address of `"C%set"`? I didn't fully understand your explanation. – Daniel Kleinstein Mar 11 '15 at 18:47
  • @DanielKleinstein - C strings are arrays of chars. So `"\021C%set"[1]` means element 1 of the array "\021C%set". Element 1 is 'C' (because element 0 is '\021'), so &("\021C%set"[1]) is the address of 'C' and the address of "C%set". – Josh Kelley Mar 11 '15 at 18:53
  • 1
    What does `\021` mean? I thought it meant the null-character followed by 2 and then 1. – Daniel Kleinstein Mar 11 '15 at 18:54
  • 1
    @DanielKleinstein - It's an [octal escape sequence](http://en.wikipedia.org/wiki/Escape_sequences_in_C). – Josh Kelley Mar 11 '15 at 18:57
1

Well, unix is 1 in this implementation. a[b] is something like *(a+b), and a+b is somethng like b+a, so &unix["\021C%set"] is something like &(*("\021C%set"+1)). Since &(*(c)) is more or less just c, this gets you "\021C%set"+1, which is a pointer to the second character, so just "C%set", which is a format string for "C" followed by a string followed by "et". \021 is an octal escape (which are 1 to 3 octal digits long; however many valid), so it only counts as one character.

Next we have (unix)["Chb"], which for the same reasons is the same as "Chb"[1], which will be the int value of the 'h' character, which in ASCII is 104. On the other side, 0X67 is 103. So we have 104+"Trick"-103, or "Trick"+1. This is the same pointer arithmetic on a string literal thing used on the left side, and it gets you "rick".

So we're left with:

printf("C%set", "rick");

Which prints "rick" between "C" and "et" (Cricket).

Samuel Edwin Ward
  • 6,526
  • 3
  • 34
  • 62