Всякий раз, когда в выражении появляется идентификатор типа массива, он преобразуется в указатель на первый элемент массива. Из-за преобразований массивы не являются lvalue. По определению операция индексирования [] интерпретируется таким образом, что E1[E2] идентично *((E1)+(E2)). В силу правил преобразования, применяемых к +, если E1 массив и E2 целое, то E1[E2] отностится к E2-ому члену E1. Поэтому, несмотря на такое проявление асимметрии, индексирование является коммуттивной операцией.

Это правило сообразным образом применяется в случае мнгомерного массива. Если E является n-мерным массивом ранга i* j*...*k, то возникающее в выражении E преобразуется в указтель на (n-1)-мерный массив ранга j*...*k. Если к этому укзателю, явно или неявно, как результат индексирования, примняется операция *, ее результатом является (n-1)-мерный массив, на который указывалось, который сам тут же преобразется в указатель.

Рассмотрим, например,

int x[3][5];

Здесь x – массив целых размером 3*5. Когда x возникает в выражении, он преобразуется в указатель на (первый из трех) 5 – элементный массив из целых. В выражении x[i], которое экввалентно *(x+i), x сначала преобразуется, как было сказано, в указатель, затем i преобразуется к типу x, что включает в сбя умножение i на длину объекта, на который указывает указтель, а именно объект из 5 целых. Результаты складываются, и используется косвенная адресация для получения массива (из 5 целых), который в свою очередь преобразуется в указатель на первое из целых. Если есть еще один индекс, снова используеся тот же параметр; на этот раз результатом является целое.

Именно из всего этого проистекает то, что массивы в С++ хранятся строкообразно (быстрее всего изменяется последний индекс), и что в описании первый индекс помогает определить объем памяти, поглощаемый массивом, но не играет никакой дргой роли в вычислениях индекса.