40
votes

A friend of mine is learning C++ for the first time, and sent me this snippet:

int foo[] = { 3, 38, 38, 0, 19, 21, 3, 11, 19, 42 };
char bar[] = " abcdefghijklmnopqrstuvwxyz01234567890+-,.!?-_";
for (int i = 0; i < 10; ++i) {
  std::cout << foo[i][bar];
}

At a glance, I told him it won't work - I thought it wouldn't compile, or would at least result in an access violation, as foo isn't a two-dimensional array, to which he replied that it does.

I tried for myself, and to my surprise, the snippet ran perfectly fine. The question is: why?

According to logic, common sense and good practice, the syntax should be bar[foo[i]].

I'm ashamed to admit that I have no idea what's going on. What makes foo[i][bar] valid syntax in this case?

1
This is not an exact duplicate, and the answer is pretty interesting. The root cause for both questions is the same, but that is true for hundreds of questions on StackOverflow.David Pfeffer
BTW: I would only agree with the output if I would be doing these sort of things...stefaanv
Amusingly, this one actually makes sense if one reads the linked question, yet still remains exactly as illogical as it is when you don't understand it; the illogical part merely shifts from "how does this work" to "why did they let this work".Justin Time - Reinstate Monica
This is less a question of syntax than of semantics.Peter - Reinstate Monica

1 Answers

47
votes

In simplistic terms, the access of an array element in C (and in C++, when [] isn't overloaded) is as follows:

x[i] = *(x + i)

So, with this and a little bit of arithmetic...

  foo[i][bar]
= (foo[i])[bar]
= (*(foo + i))[bar]
= *((*(foo + i)) + bar)
= *(bar + (*(foo + i)))
= bar[*(foo + i)]
= bar[foo[i]]

Don't use this "fact" though. As you've seen, it makes the code unreadable, and unreadable code is unmaintainable.