C инициализация массивов указателей - PullRequest
5 голосов
/ 21 июля 2011

Я совершенно сбит с толку, в чем разница между этими двумя инициализациями:

    int (*p)[10];

и

    int *p[10]

Я знаю, что они оба могут указывать на 2D-массив, количество элементов в строке которого равно 10 ...

Ответы [ 6 ]

4 голосов
/ 21 июля 2011

Первый - указатель на массив, второй - массив указателей.

2 голосов
/ 21 июля 2011
int (*p)[10];


+------+                           +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|  p   | =========================>|(*p)[0]|(*p)[1]|(*p)[2]|(*p)[3]|(*p)[4]|(*p)[5]|(*p)[6]|(*p)[7]|(*p)[8]|(*p)[9]|
+------+                           +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+

sizeof p вернет sizeof (void *) (4 на 32-битных системах, 8 на 64-битных системах)

sizeof *p вернет 10*sizeof (int) (40 в большинстве систем)

int *p[10];   is the same as     int* (p[10]);   

p
+------+------+------+------+------+------+------+------+------+------+
| p[0] | p[1] | p[2] | p[3] | p[4] | p[5] | p[6] | p[7] | p[8] | p[9] |
+------+------+------+------+------+------+------+------+------+------+

sizeof p вернет 10*sizeof (void *) (40 в 32-битных системах, 80 в 64-битных системах)

sizeof *p вернет sizeof (int *) (4 в 32-битных системах, 8 в 64-битных системах)

2 голосов
/ 21 июля 2011

Чтобы уточнить некоторые правильные ответы уже здесь:

Первая строка:

 int (*p)[10];

объявляет, что «p» является указателем на адрес памяти массива с емкостью 10 дюймов. На английском языке его можно прочитать следующим образом: «целочисленный указатель« p »указывает на 10 последовательных целых в памяти».

Вторая строка:

int *p[10]

Объявляет, что "p []" - это массив из 10 указателей на целые числа. Это массив адресов памяти, которые указывают на целые числа. В этом случае «p» - это последовательность из 10 указателей в памяти (которые являются адресами памяти других целых).

1 голос
/ 21 июля 2011

В вашем первом примере p - указатель на массив из 10 целых чисел. Во втором примере p - это массив из 10 указателей.

Вы можете динамически выделить объект типа «указатель на массив из десяти целых» следующим образом.

int (**ptr)[10] = new (int (*)[10]);

Обратите внимание, место для любых целых не выделено; только сам указатель.

Вы можете выделить массив из 10 дюймов следующим образом:

int *ptr = new int[10];

Чего вы не можете сделать (без явного приведения), так это назначить указатель на динамически размещенный массив из 10 int указателю типа int (*)[10]. Всякий раз, когда вы выделяете массив с помощью new, даже если вы используете typedef, тип нового выражения - указатель на первый элемент массива; размер массива не сохраняется в типе нового выражения.

Это связано с тем, что выражения new[] могут выделять массивы там, где размер массива выбирается во время выполнения, поэтому не всегда возможно (или даже желательно) кодировать размер массива в тип нового выражения.

Как уже было предложено, вы можете динамически выделить массив из одного массива из 10 int. Размер первого массива теряется из информации о типе, и вы получаете указатель на первый элемент массива (размером 1) из массивов из четырех int.

int (*p)[10] = new int[1][10];

Несмотря на то, что это массив всего 1 (массивы 10 int), вам все равно нужно использовать delete[] для освобождения p.

delete[] p;

Конечно, на самом деле никогда не должно быть положения, в котором нужно вызывать delete вручную.

0 голосов
/ 21 июля 2011

Как уже отмечали другие, int (*p)[10] объявляет p как указатель на массив из 10 элементов int, тогда как int *p[10] объявляет p как массив из 10 элементов указателя на int ,

В C объявления строятся вокруг типов выражений , а не объектов. Идея состоит в том, что форма объявления должна соответствовать форме выражения, как оно используется в коде.

Предположим, что p - это массив указателей на int (второй случай). Чтобы получить доступ к определенному целочисленному значению, вы должны добавить в массив и разыменовать результат, как в

x = *p[i];

Операторы постфикса, такие как [] и (), имеют более высокий приоритет, чем унарные операторы, такие как *, поэтому приведенный выше оператор анализируется как *(p[i]) (IOW, * применяется к выражению p[i]) ,

Тип выражения *p[i] равен int, поэтому соответствующее объявление p равно int *p[10];.

Теперь давайте предположим, что p - указатель на массив int (первый случай). Чтобы получить доступ к конкретному целочисленному значению, вы должны разыменовать указатель, а затем добавить результат, как в

x = (*p)[i];

Опять же, поскольку [] имеет более высокий приоритет, чем *, нам нужно использовать круглые скобки, чтобы явно связать * с p, а не p[i]. Тип выражения (*p)[i] равен int, поэтому объявление p равно int (*p)[10];.

0 голосов
/ 21 июля 2011

В первом определении (не инициализация), p - указатель;во втором p - это массив из 10 указателей.

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