1

Can anyone please help me understand the following code:

int d = 4;
printf(&d["Hay!Hello %c\n"], &4["BuddyWorld"]);           // Hello (some address in char)
printf(&d["Hay!Hello %c\n"], 4["BuddyWorld"]);            // Hello y
printf(&d["Hay!Hello %s\n"], 4["BuddyWorld"]);            // Segmentation fault
printf(&d["Hay!Hello %s\n"], &4["BuddyWorld"]);           // Hello yWorld

printf("d[Hay!Hello %s\n"], &4["BuddyWorld"]);      
/* warning: passing argument 1 of 'printf' makes pointer 
   from integer without a cast                           */

What is exactly the d[] or &d[] operator? (d is an integer) Why does &4["BuddyWorld"] and 4[BuddyWorld] yields to different values? ('W' and 'y' respectively)

zeronone
  • 2,912
  • 25
  • 28
  • 3
    `a[i]` and `i[a]` are both the same, `*(a + i)`. Does that help? – Daniel Fischer Oct 22 '12 at 15:04
  • But I still didn't get why `&4[BuddyWorld]` and `4[BuddyWorld]` yields to different values? ('W' and 'y' respectively) – zeronone Oct 22 '12 at 15:16
  • @zeronone 4["BuddyWorld"] is `'y'`, the fifth character. `&4["BuddyWorld"]` is its address, i.e. the address of `"BuddyWorld"` with an offset. – Ismail Badawi Oct 22 '12 at 15:17
  • @isbadawi Did you mean `("BuddyWorld" + 4)` is equal to `&4["BuddyWorld"]`. Doesn't the `"%c"` conversion specifier requires an argument of char type (not char * type)? – zeronone Oct 22 '12 at 15:22
  • 1
    What @isbadawi said, and when (part of) the address is interpreted as an `int` that is to be printed as a `char`, what you get depends on where the string literal is stored, and when you try to interpred the character 'y' as an address, it usually doesn't point to memory you're allowed to access, hence segfault. - `"BuddyWorld" + 4` indeed becomes `&"BuddyWorld"[4]`. The `%c` format expects an `int` (that should be the result of promoting a `char`). Passing an argument of type `char*` is undefined behaviour, but it compiles because in general, typechecking of `printf` arguments isn't possible. – Daniel Fischer Oct 22 '12 at 15:22
  • possible duplicate of [In C arrays why is this true? a\[5\] == 5\[a\]](http://stackoverflow.com/questions/381542/in-c-arrays-why-is-this-true-a5-5a) – Bo Persson Oct 22 '12 at 16:54

3 Answers3

3

When you write something like a[i], it gets expanded into *(a + i). (We say a[i] is syntactic sugar for *(a + i)).

Addition is commutative, so "BuddyWorld"[4] = *("BuddyWorld" + 4) = *(4 + "BuddyWorld") = 4["BuddyWorld"], where "BuddyWorld" implicitly stands for its address in memory.

Ismail Badawi
  • 36,054
  • 7
  • 85
  • 97
2

Subscripting in C is weird. a[b] is turned into *(a + b) (the thing at the address obtained by adding b to the pointer a). However, since a + b == b + a, it works the other way around as well (a[b] == b[a]). That's all that's going on. In particular, "HelloWorld" is really a pointer to a character array that stores the characters of the string.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • In the first two lines, why does the `&4["BuddyWorld"]` and `4["BuddyWorld"]` yields to different values? – zeronone Oct 22 '12 at 15:09
  • 2
    @zeronone - `4["BuddyWorld"]` is the same as "BuddyWorld"[4] -- the character "y" (actually, the `int` value 121). But what's happening with `&4["BuddyWorld"]`? The expression is the address of the string "yWorld" (the substring that starts at offset 4). It is as if you had called `printf("Hello %c\n", "yWorld");` What happens when you pass a string argument to a `%c` format conversion? It treats the address of the string as an unsigned int and prints the corresponding ASCII character. I think it's a coincidence that you got a familiar character (I don't when I run your code). – Ted Hopp Oct 22 '12 at 15:30
  • Oh Thanks, I got it. It was funny coincidence :) – zeronone Oct 22 '12 at 15:35
1

d["Hay!Hello %c\n"] is the same as "Hay!Hello %c\n"[d].

And the & operator gives the address of the pointed content

MByD
  • 135,866
  • 28
  • 264
  • 277