Чтобы ваша переменная ptr
была "адресом массива целых чисел", вам действительно нужно более тонкое (и загадочное) объявление.
Это будет работать:
int (*ptr)[10] = &test;
, поскольку он объявляет, что при разыменовании (то есть когда вы на самом деле используете выражение *ptr
), это будет массив (из 10 элементов).
In в некотором смысле, структура объявления немного похожа на структуру для указателей на функции .
EDIT: во втором случае test
- это простой старый указатель (с значение, присвоенное ему вызовом malloc
); как таковая, она сама является переменной , адрес которой может быть взят (как ваша строка int **ptr = &test;
делает - правильно).
Однако в первом случае (массив 'fixed') test
относится к блоку памяти; во многих отношениях это может быть , используемый в качестве указателя на первый элемент (как, например, при вызове функции). Но какое значение компилятор может присвоить «адресу адреса первого элемента»? Это то, что в данном случае не выполняется при попытке присвоения с использованием &test
.
Но вы, согласно предыдущему абзацу, имеете право спросить, как компилятор определяет значение для &test
(для присвоить ptr
) с кодом, указанным в этом ответе? Хорошо, если вы добавите следующую строку в вашу программу:
printf("%p %p\n", test, &test);
вы увидите, что test
и &test
(вы можете изменить &test
на ptr
- вывод будет таким же ) имеют точно такое же значение ! Таким образом, используя это «тайное» объявление, вы даете компилятору достаточно информации, чтобы знать, что делать с «указателем массива» - по сути, он как бы «игнорирует» (или обходит) первый уровень разыменования, заканчивающийся адресом первого элемента массива (как есть).