【C语言】✅如何理解函数中形参数组的维度规则

1,235 阅读4分钟

维度规则

在C语言中,如果函数的参数是数组,则有以下几种表示方式:

1. 指定每一维的大小:明确规定数组每一维的大小。

2. 省略第一维的大小:省略数组的第一维大小,但必须指定其他维的大小。

3. 不能省略第二维的大小:在函数参数列表中,不能省略第二维及其后的维数。

举例

假设我们定义一个处理二维数组的函数。

指定每一维的大小

void processArray(int array[3][4]) {
    // 处理数组的代码
}

在这个例子中,我们明确规定了数组的每一维大小。

省略第一维的大小

void processArray(int array[][4], int rows) {
    // 处理数组的代码
}

在这个例子中,我们省略了第一维的大小,使用rows参数来传递数组的行数。

不能省略第二维的大小

void processArray(int array[3][]) { 
    // 错误:必须指定第二维的大小
}

在这个例子中,省略第二维的大小是不允许的,编译器无法确定每一行的大小。

具体示例

#include <stdio.h>

void printArray(int array[][4], int rows) {
    for(int i = 0; i < rows; i++) {
        for(int j = 0; j < 4; j++) {
            printf("%d ", array[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int array[2][4] = { {1, 2, 3, 4}, {5, 6, 7, 8} };
    printArray(array, 2);
    return 0;
}

在这个示例中,printArray函数省略了第一维的大小,而在调用时传递了行数rows。第二维的大小(列数)必须明确指定为4。通过这种方式,C语言允许灵活地传递多维数组作为函数参数,同时确保编译器能够正确理解数组的结构。

为什么只能省略第一维?

函数的形参数组只能省略第一维的大小,而不能省略第二维及其后的大小,这是因为编译器在处理数组时需要明确知道每个元素的大小和布局。

1. 内存布局的确定:编译器需要知道每个元素在内存中的确切位置。当你声明一个二维数组int array[][4]时,编译器知道每一行有4个整数,所以可以正确计算每个元素的地址。如果你省略了第二维及其后的维数,编译器无法知道每一行有多少个元素,从而无法正确计算每个元素的地址。

2. 数组的连续存储:C语言中,多维数组是以连续的内存块存储的。例如,一个二维数组int array[3][4]实际上是一个包含12个整数的一维数组,按行优先顺序存储。编译器需要知道第二维的大小来正确地计算每个元素的位置。

接着举例

为了更好地理解这一点,我们可以通过一些代码示例来解释。

可以省略第一维

void processArray(int array[][4], int rows) {
    for(int i = 0; i < rows; i++) {
        for(int j = 0; j < 4; j++) {
            // 处理每个元素
        }
    }
}

在这个例子中,虽然省略了第一维的大小,但编译器知道第二维的大小是4,因此可以正确地计算每个元素的位置。

不能省略第二维

void processArray(int array[3][]) { 
    // 错误:必须指定第二维的大小
}

在这个例子中,省略了第二维的大小,编译器无法知道每一行有多少个元素,因此无法正确地计算每个元素的位置。

更深层次的理解

对于编译器来说,多维数组的内存布局非常重要。假设我们有一个三维数组:

int array[2][3][4];

这实际上被存储为一个一维数组,按顺序存储每个元素:

array[0][0][0], array[0][0][1], ..., array[0][0][3],
array[0][1][0], array[0][1][1], ..., array[0][1][3],
...
array[1][2][0], array[1][2][1], ..., array[1][2][3]

编译器需要知道每一维的大小来正确地解析这个内存布局。如果你省略了第二维或更高维的大小,编译器将无法正确地计算每个元素的位置,因为它不知道每一行或每一块内存的边界在哪里。