给函数传递多维数组很容易让人迷惑,尤其是在用指针表示法的情况下。传递多维数组时,我们要决定在函数签名1中使用数组表示法还是指针表示法。还有一件要考虑的事情是如何传递数组的形态,这里所说的形态是指数组的维数及每一维的大小。要想在函数内部使用数组表示法,必须指定数组的形态,否则,编译器就无法使用下标。
1 函数签名是指函数原型声明。——译者注
要传递数组matrix
,可以这么写:
void display2DArray(int arr[][5], int rows) {
或者这么写:
void display2DArray(int (*arr)[5], int rows) {
这两种写法都指明了数组的列数,这很有必要,因为编译器需要知道每行有几个元素。如果没有传递这个信息,编译器就无法计算4.7节讲到的arr[0][3]
这样的表达式。
在第一种写法中,表达式arr[]
是数组指针的一个隐式声明,而第二种写法中的(*arr)
表达式则是指针的一个显式声明。
警告 下面的声明是错误的:
void display2DArray(int *arr[5], int rows) {
尽管不会产生语法错误,但是函数会认为传入的数组拥有5个整数指针。4.6节讨论了指针数组。
这个函数的简单实现和调用方法如下:
void display2DArray(int arr[][5], int rows) {
for (int i = 0; i<rows; i++) {
for (int j = 0; j<5; j++) {
printf("%d", arr[i][j]);
}
printf("\n");
}
}
void main() {
int matrix[2][5] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10}
};
display2DArray(matrix, 2);
}
函数不会为这个数组分配内存,传递的只是地址。本次调用的程序栈状态如下图所示。
你可能会遇到下面这样的函数,接受的参数是一个指针和行列数:
void display2DArrayUnknownSize(int *arr, int rows, int cols) {
for(int i=0; i<rows; i++) {
for(int j=0; j<cols; j++) {
printf("%d ", *(arr + (i*cols) + j));
}
printf("\n");
}
}
printf
语句通过给arr
加上前面行的元素数(i*cols)
以及表示当前列的j
来计算每个元素的地址。要调用这个函数可以这么写:
display2DArrayUnknownSize(&matrix[0][0], 2, 5);
在函数内我们无法像下面这样使用数组下标:
printf("%d ", arr[i*cols][j]);
原因是没有将指针声明为二维数组。不过,倒是可以像下面这样使用数组表示法。我们可以用一个下标,这样写只是解释为数组内部的偏移量,不能用两个下标是因为编译器不知道一维的长度:
printf("%d ", (arr+i)[j]);
这里传递的是&matrix[0][0]
而不是matrix
,尽管用matrix
也能运行,但是会产生编译警告,原因是指针类型不兼容。&matrix[0][0]
表达式是一个整数指针,而matrix
则是一个整数数组的指针。
在传递二维以上的数组时,除了第一维以外,需要指定其他维度的长度。下面这个函数打印一个三维数组,声明中指定了数组的后二维。
void display3DArray(int (*arr)[2][4], int rows) {
for(int i=0; i<rows; i++) {
for(int j=0; j<2; j++) {
printf("{");
for(int k=0; k<4; k++) {
printf("%d ", arr[i][j][k]);
}
printf("}");
}
printf("\n");
}
}
下面说明如何调用这个函数:
int arr3d[3][2][4] = {
{{1, 2, 3, 4}, {5, 6, 7, 8}},
{{9, 10, 11, 12}, {13, 14, 15, 16}},
{{17, 18, 19, 20}, {21, 22, 23, 24}}
};
display3DArray(arr3d,3);
输出如下所示:
{1 2 3 4 }{5 6 7 8 }
{9 10 11 12 }{13 14 15 16 }
{17 18 19 20 }{21 22 23 24 }
数组的内存分配如下图所示。
arr3d[1]
表达式引用数组的第二行,是一个2行4列的二维数组的指针。arr3d[1][0]
引用数组的第二行第一列,是一个长度为16的一维数组的指针。