Как правило, единственный раз, когда вы увидите указатель на массив (T (*a)[N]
) в качестве параметра функции, где a
означает 2d массив:
void foo(int (*a)[N], size_t count)
{
size_t i;
for (i = 0; i < count; i++)
a[i][j] = ...;
...
}
void bar(void)
{
int arr[M][N];
foo(arr, M);
}
Обратите внимание, что для объявления параметров функции int a[][N]
эквивалентно int (*a)[N]
, но это только true для объявлений параметров функции:
void foo (int a[][N], size_t count) {...}
Указатели на массивы, как правило, не так полезны, как указатели на базовый тип, поскольку для правильного объявления указателя на него необходимо знать размер массива (указатель на массив из 10 элементов типа int отличается от типа указатель на массив из 20 элементов типа int). Лично я не нашел для них особого смысла за 20 с лишним лет программирования.
Помните, что в большинстве контекстов выражение массива (такое как arr
выше) будет иметь свой тип, неявно преобразуемый из "массива N-элементов T" в "указатель на T" (кроме случаев, когда выражение массива является операндом sizeof
или &
, или массив является строковым литералом, используемым в качестве инициализатора в объявлении). В этом случае тип arr
в вызове foo неявно преобразуется из «массива M-элементов массива N-элементов типа int» в «указатель на массив N-элементов массива int».
Учитывая объявление T a[M][N]
, все следующие выражения будут оцениваться в одном и том же месте (адрес первого элемента в массиве), но типы будут отличаться, как показано ниже:
Expression Type Implicitly converted to
---------- ---- -----------------------
a T [M][N] T (*)[N]
a[0] T [N] T *
&a T (*)[M][N]
&a[0] T (*)[N]
&a[0][0] T *