Удивительные указатели - PullRequest
2 голосов
/ 14 октября 2010

Я удивлен, увидев, что этот сегмент кода печатает одинаковый адрес для всех трех указателей.

int main(int argc,char *argv[])
{
   int arr[3][3];
   printf("%p\n%p\n%p\n",arr,*arr,arr[0]);
   return 0;
}

Почему это так?

Ответы [ 4 ]

4 голосов
/ 14 октября 2010

См. Так что же понимается под "эквивалентностью указателей и массивов" в C?

Адрес массива - это адрес его первого элемента. И arr[i] эквивалентно *(arr + i) для любого массива arr. Следовательно, arr[0] совпадает с *(a + 0).

3 голосов
/ 14 октября 2010

C выкладывает многомерные массивы плоскими, если по крайней мере все, кроме последнего измерения известны во время компиляции - так что int[3][3] на самом деле просто и int[9] массив в памяти - только тип отличается.

Таким образом, поскольку массив молча преобразуется в указатель на свой первый элемент при использовании в большинстве выражений, *arr всегда эквивалентно arr [0] для всех массивов. В этом случае arr (два уровня косвенности на int) - указатель на первый массив int[3], *arr==arr[0] (1 уровень косвенности на int) - указатель на первое целое число в первом int[3] массив, поскольку вся структура «плоская», этот первый int[3] начинается точно в том же месте, что и массив int[3][3].

Это немного сбивает с толку, но в памяти это всего лишь 9 целых чисел подряд, которые "знает" компилятор, следует рассматривать как блоки из 3

если ячейки указаны ниже:

|0|1|2|3|4|5|6|7|8|

тогда arr - указатель на | 0 |, arr+1 - указатель на | 3 | и arr+2 - указатель на | 6 |

arr[0] ТАКЖЕ указатель на | 0 |, arr[0]+1 указатель на | 1 |, arr[0]+2 указатель на | 2 | и так далее... Поскольку arr[0] всегда идентичен *arr для любого массива, *arr ТАКЖЕ является указателем на | 0 |

3 голосов
/ 14 октября 2010

Поскольку адрес массива равен адресу начального элемента.

Это означает, что адрес arr[1] равен адресу arr + 1 и адресу *(arr + 1).

1 голос
/ 14 октября 2010

arr - это адрес первого элемента в массиве, который также является адресом первой строки массива из-за того, как C размещает многомерные массивы в памяти.

arr[0] возвращает указатель на первую строку, что эквивалентно arr

*arr = arr[0] как и со всеми указателями C

в основном все они одинаковы из-за способа, которым C выкладывает многомерные массивы, адрес начала массива также является адресом первой строки массива.

Часть этой путаницы заключается в том, что, хотя для одномерного массива arr[], arr можно рассматривать как указатель, как если бы он был определен как '* arr'. Это не относится к многомерным массивам. arr[][] нельзя рассматривать как двойной указатель, как если бы он был определен **arr. это очень разные типы данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...