Компилятор дает довольно хорошую подсказку:
~$ gcc mat.c
mat.c: In function ‘main’:
mat.c:22:12: warning: passing argument 1 of ‘modify’ from incompatible pointer type [-Wincompatible-pointer-types]
modify(x, 5, 5);
^
mat.c:3:17: note: expected ‘int (*)[5]’ but argument is of type ‘int **’
void modify(int x[5][5], int m, int n) {
~~~~^~~~~~~
Объявление int x[5][5]
объявляет массив массивов.Это нечто совершенно отличное от int *x[5];
, которое объявляет массив указателей.Интересный факт: добавьте круглые скобки вот так int (*x)[5]
, и вместо этого вы получите указатель на массив int размера 5. Вот хороший сайт, который переводит объявления C на английский: https://cdecl.org/
IsЕсть ли разница между передачей массива в стеке и массива в куче?
Динамически выделяемая память обычно заканчивается в куче, а остальные обычно идет в стек.Тем не менее, это всего лишь деталь реализации, и ничто в стандарте C не требует наличия кучи или стека вообще.
Когда вы передаете массив функции, он будет распадаться на указатель на его первый элемент.Функция не будет знать, где находятся данные (хммм, хорошо, поскольку указатель имеет фактический адрес, который он делает, но не знает о куче или стеке) или как они были распределены.Итак, рассмотрим следующий фрагмент кода:
void setToZero(int * arr, int size) {
for(int i=0; i<size; i++) arr[i] = 0;
}
Функция будет иметь ТОЧНО одинаковый эффект для x
и y
:
int x[10];
int *y = malloc(10 * sizeof *y);
setToZero(x);
setToZero(y);