Почему это работает? Нелогичный доступ к массиву

Мой друг впервые изучает C++ и прислал мне этот фрагмент кода:

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];
}

С первого взгляда я сказал ему, что это не сработает — я думал, что это не скомпилируется или, по крайней мере, приведет к нарушению прав доступа, поскольку foo не является двумерным массивом, на что он ответил, что работает.

Я попробовал сам, и, к моему удивлению, фрагмент работал нормально. Вопрос: почему?

Согласно логике, здравому смыслу и хорошей практике синтаксис должен быть bar[foo[i]].

Мне стыдно признаться, что я понятия не имею, что происходит. Что делает foo[i][bar] допустимым синтаксисом в этом случае?


person untitled8468927    schedule 18.01.2012    source источник
comment
Это не точная копия, и ответ довольно интересный. Основная причина обоих вопросов одна и та же, но это верно для сотен вопросов на StackOverflow.   -  person David Pfeffer    schedule 18.01.2012
comment
Кстати: я бы согласился с выводом только в том случае, если бы занимался такими вещами...   -  person stefaanv    schedule 18.01.2012
comment
Забавно, но этот вопрос действительно имеет смысл, если прочитать связанный вопрос, но все же остается таким же нелогичным, как и тогда, когда вы его не понимаете; нелогичная часть просто переходит от того, как это работает, к тому, почему они позволили этому работать.   -  person Justin Time - Reinstate Monica    schedule 31.12.2016
comment
Это вопрос не столько синтаксиса, сколько семантики.   -  person Peter - Reinstate Monica    schedule 06.05.2020


Ответы (1)


Проще говоря, доступ к элементу массива в C (и в C++, когда [] не перегружен) выглядит следующим образом:

x[i] = *(x + i)

Итак, с этим и немного арифметики...

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

Однако не используйте этот «факт». Как вы видели, это делает код нечитаемым, а нечитаемый код невозможно поддерживать.

person Adam Wright    schedule 18.01.2012