C传递多维数组

给函数传递多维数组很容易让人迷惑,尤其是在用指针表示法的情况下。传递多维数组时,我们要决定在函数签名中使用数组表示法还是指针表示法。还有一件要考虑的事情是如何传递数组的形态,这里所说的形态是指数组的维数及每一维的大小。要想在函数内部使用数组表示法,必须指定数组的形态,否则,编译器就无法使用下标。

要传递数组matrix,可以这么写:

void display2DArray(int arr[][5], int rows) {

或者这么写:

void display2DArray(int (*arr)[5], int rows) {

这两种写法都指明了数组的列数,这很有必要,因为编译器需要知道每行有几个元素。如果没有传递这个信息,编译器就无法计算指针和多维数组讲到的arr[0][3]这样的表达式。

在第一种写法中,表达式arr[]是数组指针的一个隐式声明,而第二种写法中的(*arr)表达式则是指针的一个显式声明。

警告 下面的声明是错误的:

void display2DArray(int *arr[5], int rows) {

尽管不会产生语法错误,但是函数会认为传入的数组拥有5个整数指针。指针数组讨论了指针数组。

这个函数的简单实现和调用方法如下:

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);
}

函数不会为这个数组分配内存,传递的只是地址。本次调用的程序栈状态如图4-13所示。

图4-13:传递多维数组

你可能会遇到下面这样的函数,接受的参数是一个指针和行列数:

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 }

数组的内存分配如图4-14所示。

enter image description here

图4-14:三维数组

arr3d[1]表达式引用数组的第二行,是一个2行4列的二维数组的指针。arr3d[1][0]引用数组的第二行第一列,是一个长度为16的一维数组的指针。

赞(1)

评论 抢沙发

评论前必须登录!

 

C指针