Это не одно и то же.
Массив - это объект, состоящий из последовательности одного или нескольких смежных элементов, одинакового типа. 2-мерный массив - это не что иное, как массив массивов.
имя из массива - это выражение. Как и любое выражение типа массива, он в большинстве, но не во всех контекстах неявно преобразуется в указатель на первый элемент массива. Исключения составляют, когда это операнд sizeof
(sizeof arr
дает размер объекта массива, а не размер указателя), и когда он является операндом унарного &
(&arr
дает адрес всего массива).
Адрес адрес массива подобен адресу любого объекта. Он относится к определенному адресу памяти и имеет тип: указатель на тип массива. Например, учитывая:
int arr[10];
выражение arr
(если это не операнд &
или sizeof
) дает адрес arr[0]
, и имеет тип int*
. Выражение &arr
дает адрес всего массива; это то же место памяти, но оно имеет тип int (*)[10]
, или «указатель на массив из 10 int
s».
Значение значения из массива, как правило, не является тем, о чем вы можете напрямую обратиться. Он состоит из значений элементов массива.
Теперь давайте посмотрим на вашу программу:
#include <stdio.h>
int main(void)
{
int array[4][2]={1,2,3,4,5,6,7,8};
Это более четко написано, как:
int array[4][2] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
printf("%d %d\n",
&array[0][0], array[0][0]);
array[0][0]
является int
объектом, так &array[0][0]
является его адрес, и это o f тип int*
. Правильный способ печати адреса (значение указателя) заключается в использовании формата %p
; он ожидает аргумент типа void*
, поэтому вы должны его преобразовать.
printf("%p %d\n", (void*)&array[0][0], array[0][0]);
printf("%d %d %d %d\n",
array, &array, *array, **array);
array
является выражение типа массива, поэтому она «распады» до указателя на первый элемент этого массива. Этот элемент имеет тип int[2]
, поэтому указатель имеет тип int(*)[2]
. Опять же, вы должны использовать %p
и конвертировать в void*
.
&array
- адрес всего массива. Это тип int(*)[4][2]
.
В *array
подвыражение array
распадается на указатель. *
, затем разыгрывает этот указатель, который дает нам объект типа int[2]
(первый элемент массива). Это выражение типа массива, поэтому оно снова отклоняет указателю на первый элемент этого массива. Это тип int*
.
В **array
, *array
оценивается, как указано выше; это указатель на объект int
. Следующие *
разыменовывают этот указатель, давая значение int
.
Все значения указателя, которые вы напечатали, указывают на один и тот же адрес памяти, но они различаются по типу int*
, int(*)[2]
или int(*)[2][4]
. Каждый из этих указателей, при преобразовании в void*
, дает то же значение, и все они
}
Сведя вместе, вот исправленная версия вашей программы:
#include <stdio.h>
int main(void)
{
int array[4][2] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
printf("%p %d\n",
(void*)&array[0][0], array[0][0]);
printf("%p %p %p %d\n",
(void*)array, (void*)&array, (void*)*array, **array);
}
Выход на мой (64-битная) система:
0x7fffc5070b30 1
0x7fffc5070b30 0x7fffc5070b30 0x7fffc5070b30 1
взаимосвязь между массивами и указателями в C может ввести в заблуждение. Большая часть путаницы может быть устранена путем чтения раздела 6 раздела comp.lang.c FAQ.
Вы должны добавить языковой тег. – csmckelvey
Можете ли вы поделиться выходом. Используйте gdb для отладки. Это очень полезно – Jigar
У меня есть выборка в моем ответе. (И я знаю, что использование% u для указателей является nono :) – eckes