Ну, это, конечно, не очень понятно сообществом Си, что можно увидеть, взглянув на SO. Волшебство в том, что все следующее полностью, 100%, эквивалентно :
void foo(int (*array)[10]);
void foo(int array[][10]);
void foo(int array[10][10]);
void foo(int array[42][10]);
Очень важно провести различие между указателем и массивом. Массив не является указателем . Массив может быть преобразован в указатель на его первый элемент. Если у вас есть указатель, у вас есть это:
--------
| ptr | -------> data
--------
Однако, если у вас есть массив, у вас есть это:
---------------------------
| c1 | c2 | c3 | ... | cn |
---------------------------
С указателем данные находятся на другой планете, но связаны с указателем. Массив содержит сами данные. Теперь многомерный массив - это просто массив массивов. Массивы вложены в родительский массив. Итак, размер вашего массива:
(sizeof(int) * 10) * 10
Это потому, что у вас есть 10 массивов, каждый из которых является массивом из 10 целых чисел. Теперь, если вы хотите передать этот массив, он конвертируется. А к чему? Указатель на его первый элемент. Тип элемента не указатель, а массив. Как следствие, вы передаете указатель на массив из 10 int:
int (*)[10] // a pointer to an int[10]
Это ни массив int*
, ни int**
. Вы можете спросить, почему массив не передается как int**
. Это потому, что компилятор должен знать длину строки. Если вы сделаете array[1][0]
, компилятор обратится к месту sizeof(int) * 10
байтов, кроме начала двумерного массива. Он декодирует эту информацию в виде указателя на массив.
Итак, вы должны выбрать один из приведенных выше полностью эквивалентных прототипов функций. Естественно, последний просто сбивает с толку. Компилятор просто молча игнорирует любое число, записанное в самом внешнем измерении, если параметр объявлен как массив. Так что я бы тоже не стал использовать вторую последнюю версию. Лучше всего использовать первую или вторую версию. Важно помнить, что C не имеет (реальных) параметров массива ! Параметр в конце будет указателем (в данном случае указателем на массив).
Обратите внимание, что многомерный случай выше похож на вырожденный, одномерный случай ниже. Все следующие 4 версии полностью эквивалентны:
void foo(int *array);
void foo(int array[]);
void foo(int array[10]);
void foo(int array[42]);