Указатели и массивы
Нетрудно заметить, что указатель в Си имеет много общего с массивом. Наоборот, труднее сформулировать, чем они отличаются друг от друга. Действительно, разница лежит не в принципе работы с указуемыми переменными, а в способе назначения указателя и массива на ту память, с которой они работают. Образно говоря, указателю соответствует массив, "не привязанный" к конкретной памяти, а массиву соответствует указатель, постоянно назначенный на выделенную транслятором область памяти. Рассмотрим сходства и различия в использовании указателей и массивов на следующем примере.
.
int A[20]; int *p;
При определении массива происходит резервирование памяти заданного размера, в дальнейшем имя массива интерпретируется как ее начальный адрес. При определении указателя с ним не связывается никакая область памяти.
.
A; или &A[0];
Идентификатор массива без скобок интерпретируется как начальный адрес массива, или указатель на нулевой элемент.
.
p = A; p = &A[0];
Перед началом работы с указателем его необходимо назначить на некоторую область памяти, в данном случае -на начало массива.
.
p = &A[5];
p = A + 5;
Указатель может быть назначен также на любую область памяти, в данном случае -на 5-й элемент массива;
.
A[i] *(p + i)
&A[i] p + i
A + i &p[i]
*(A + i) p[i]
Работа с областью памяти как с обычным массивом, так и через указатель полностью идентична вплоть до синтаксиса: транслятор интерпретирует конструкцию p[i] как *(p+i) для любого указателя и имени массива.
.
p++;
p +=i;
m = *p++;
Указатель может перемещаться по памяти относительно своего текущего положения.
Таким образом, различие между указателем и массивом аналогично различию между переменной и константой. Указатель -это ссылочная переменная, а имя массива -ссылочная константа, привязанная к конкретному адресу памяти.