Массивы, указатели и индексирование
Всякий раз, когда идентификатор типа массив встречается в выражении, он преобразуется в указатель на первый элемент массива. Из-за этого преобразования массивы не являются л_значениями. По определению, операция индексирования [] понимается таким образом, что 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 встречается в выражении, он преобразуется в указатель на (первый из трех) пятиэлементный одномерный массив целых. В выражении x[i], эквивалентном *(x+i), x сначала преобразуется в указатель, как это описано выше, затем i преобразуется в соответствии с типом x - преобразование заключается в умножении i на размер указываемого объекта, а именно на размер пяти объектов целого типа. Результаты складываются и применяется операция *, что дает одномерный массив (из пяти целых), который в свою очередь преобразуется в указатель на первый из целых элементов. Если есть еще один индекс, выполняются те же действия; на этот раз результат будет целого типа.
Массивы в языке C размещаются построчно (последний индекс изменяется быстрее всего); первый индекс в описании дает возможность определить объем памяти, занимаемый массивом. Другой роли в исчислении индексов массивы не играют.