为什么二维数组的行为类似于一维指针数组而不是一维整数数组?

Nat*_*ows 2 c arrays pointers multidimensional-array implicit-conversion

我一直在研究和测试我在 C 方面的知识(我是一名新的计算机工程专业的学生),遇到了一个我无法弄清楚的问题。

在尝试将 2D 数组传递给函数时,我了解到您不能使用动态分配的数组这样做,因为编译器需要知道 array[][columns]。但是,我了解到二维数组存储在一维数组中,其中每个新行的元素都跟在前一行的元素之后。当我将数组名称作为指向数组的指针传递给函数时,情况似乎如此,我的代码运行良好。但是,在声明 2D 数组的函数中,它表现为一个指针数组。

#include <stdio.h>

void printArray(int *A, int* dimA) {
    for(int i = 0; i < dimA[0]; ++i) {
        for(int j = 0; j < dimA[1]; ++j) {
            printf("%3d", A[i*dimA[1] + j]);//This would work if the elements of A[] are the rows of a 2D array mapped into a 1D array
        }
    printf("\n\n");
    }
return;
}

int main(){
    int A[2][2] = {{1,2},{3,4}};
    int dimA[2] = {2,2};//dimensions of the array
    int i, j; 

    for(i = 0; i < dimA[0]; ++i) {
        for(j = 0; j < dimA[1]; ++j) {
            printf("%3d", *(A[i] + j)); //This would work if the elements of A[] are pointers
        }
        printf("\n\n");
    }

    for(i = 0; i < dimA[0]; ++i) {  //Same code as printArray function
        for(j = 0; j < dimA[1]; ++j) {
            printf("%3d", A[i*dimA[1] + j]);//This would work if the elements of A[] are the rows of a 2D array mapped into a 1D array
        }
        printf("\n\n");
    }

    printArray(A, dimA);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当数组被视为指针数组时,以下代码在 main() 中正确输出数组,但当被视为一维整数数组时则不会。但是,当我将相同的数组作为指针传递给 printArray 函数时,我可以将其视为一维整数数组并且它可以工作。任何帮助将不胜感激(我已经知道我可以使用指针数组,但我真的很想了解问题所在)。谢谢!

Vla*_*cow 5

根据 C 标准(6.3.2.1 左值、数组和函数指示符)

3 除非它是 sizeof 运算符或一元 & 运算符的操作数,或者是用于初始化数组的字符串文字,否则类型为“array of type”的表达式将转换为类型为“pointer”的表达式键入 '' 指向数组对象的初始元素并且不是左值。如果数组对象具有寄存器存储类,则行为未定义。

因此在第一个 for 循环中

for(i = 0; i < dimA[0]; ++i) {
    for(j = 0; j < dimA[1]; ++j) {
        printf("%3d", *(A[i] + j)); //This would work if the elements of A[] are pointers
    }
    printf("\n\n");
}
Run Code Online (Sandbox Code Playgroud)

表达式A[i]的类型为int[2]。被转换为指针,它的类型为int *。因此,对于每个 i 表达式A[i]指向数组的每个“行”的第一个元素A

该表达式A[i] + j指向每行的第 j 个元素。因此,取消引用指针,您将获得数组第 i 行的第 j 个元素。

在第二个循环中

for(i = 0; i < dimA[0]; ++i) {  //Same code as printArray function
    for(j = 0; j < dimA[1]; ++j) {
        printf("%3d", A[i*dimA[1] + j]);//This would work if the elements of A[] are the rows of a 2D array mapped into a 1D array
    }
    printf("\n\n");
}
Run Code Online (Sandbox Code Playgroud)

表达式A[i*dimA[1] + j]具有类型int *并指向i *dimA[1] + j数组的“行”,即它指向数组之外。所以循环没有意义。

函数声明如下

void printArray(int *A, int* dimA);
Run Code Online (Sandbox Code Playgroud)

被称为像

printArray(A, dimA);
Run Code Online (Sandbox Code Playgroud)

具有该类型的第二个参数int[2]确实被转换为指向int *数组第一个元素的类型的指针。

至于第一个参数,它也被转换为指向其第一个元素的指针。数组的元素是什么?这个二维数组的元素是一个类型为 的一维数组int[2]。所以指向这种类型的对象的指针将具有类型int ( * )[2]

指针int *int ( * )[2]不兼容,因此编译器应发出诊断消息。

函数的正确声明应该是这样的

void printArray(int ( *A )[2], int *dimA);
Run Code Online (Sandbox Code Playgroud)