很明显,C语言社区对此并不十分了解,这可以从浏览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 |
然而,如果你有一个数组,你会得到这个:
| c1 | c2 | c3 | ... | cn |
使用指针,数据存储在另一个星球上,但通过指针链接。数组本身就包含了数据。现在,多维数组只是一个数组的数组。 这些数组被嵌套到父数组中。因此,你的数组的大小为:
(sizeof(int) * 10) * 10
那是因为你有10个数组,它们都是由10个整数组成的数组。现在,如果你想传递这个数组,它会被转换。但是转换成什么呢?它的第一个元素的指针。元素类型不是指针,而是一个数组。因此,你传递的是一个指向包含10个整数的数组的指针:
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]);