Если у вас есть массив, объявленный как
T a[N];
, где T
- некоторый спецификатор типа, тогда указатель на массив будет объявлен как
T ( *p )[N] = &a;
Общее правило: последующий. Если у вас есть многомерный массив (включая одномерные массивы), например,
T a[N1][N2][N3];
, тогда эту декларацию вы можете переписать как
T ( a[N1] )[N2][N3];
Чтобы получить указатель на первый элемент массив просто подставляет содержимое в круглые скобки следующим образом
T ( *p )[N2][N3] = a;
Если вы хотите получить указатель на весь массив, перепишите объявление массива следующим образом:
T ( a )[N1][N2][N3];
и сделать подстановку
T ( *p )[N1][N2][N3] = &a;
Сравните это с объявлением скалярного объекта и указателем на него.
Например,
T obj;
Вы можете переписать объявление как
T ( obj );
Теперь, чтобы получить указатель на объект, вы можете написать
T ( *p ) = &obj;
Конечно, в этом случае круглые скобки являются избыточными, а приведенное выше объявление эквивалентно
T *p = &obj;
Что касается этого фрагмента кода
int q[10]={0};
cout << q << endl;
cout << &q << endl;
cout << &q[0] << endl;
и его вывода
0x7fffd4d2f860
0x7fffd4d2f860
0x7fffd4d2f860
, то указатели массива, используемые в выражениях с редкими исключениями, преобразуются в указатели на их первый elements.
Таким образом, на самом деле два выражения q
и &q[0]
в этих утверждениях
cout << q << endl;
cout << &q[0] << endl;
эквивалентны. С другой стороны, адрес самого массива является адресом объема памяти, который занимает массив. И в начале экстента есть первый элемент массива. Таким образом, три выражения дают один и тот же результат: адрес объема памяти, занятого массивом.