使用变量初始化数组

Nis*_*ant 3 c multidimensional-array

我试图将二维数组传递给函数.我没有把它传递给函数的麻烦.但我很难理解这背后的逻辑.功能和主要定义如下:

// Function to print the two-dimensional array
void print(int x, int y, int a[x][y]){
    printf("\n");
    int i, j;
    for(i = 0; i < x; i++){
        for(j = 0; j < y; j++)
            printf("%d     ", a[i][j]);
        printf("\n");
    }
}

// Function to initialize the two-dimensional array
void init_2d(int *a, int x, int y){
    int i, j;
    for(i = 0; i < x; i++){
        for(j = 0; j < y; j++){
            a[i*y + j] = i + j;
        }
        printf("\n");
    }
}

int main(){
    int m = 2, n = 3;
    int a[m][n];  // a two dimensional whose size has been defined using m and n
    init_2d(a, m, n);
    print(m, n, a);
}
Run Code Online (Sandbox Code Playgroud)

具有讽刺意味的是,一切正常 这是我的问题,因为我无法消化它的逻辑.

主要问题是:

  1. 我在书中读到的是,二维数组的大小应该使用常量或符号常量来定义.在我主我使用的变量定义2-d阵列mn,但它工作正常.为什么?
  2. 我还被告知通过将二维数组衰减为单维数组(通过将其定义为函数中指向int的指针)来传递二维数组,即我在函数中完成它的方式init_2d.但在print函数中我正在使用二维数组,其大小已使用变量x和定义y.这样做好吗?
  3. 是否可以使用指向指针的方式遍历二维数组?

任何人都可以建议我阅读这个主题,这可以清除我的所有概念吗?

我正在使用代码块来编译我的代码,编译器是GNU GCC Compiler.

AnT*_*AnT 7

  1. 是的,不是.您在书中阅读的内容适用于较旧的C语言规范的原始版本 - C89/90.由于C语言编译器的C99版本支持所谓的可变长度数组(VLAs),其大小可以由运行时值指定.您无意中使用了该语言的C99特定功能,编译器在其默认模式下显然支持该功能.如果您要求编译器切换到严格的C89/90模式,则代码将无法专门编译,因为您使用非常量来指定数组大小.

    请注意,即使在C99中,仅在某些上下文中支持VLA,如本地数组和函数参数声明.您将无法声明静态VLA或作为结构类型成员的VLA.在这些情况下,即使在C99中,仍然需要使用常量数组大小.

  2. 谁告诉你将2D阵列衰减到1D阵列是非常错误的.您init_2d在程序中使用的方式无效:您不能自己将2D数组"重新解释"为一维数组.任何C编译器都会立即抱怨你

    init_2d(a, m, n);
    
    Run Code Online (Sandbox Code Playgroud)

    调用,因为此调用尝试传递int参数的2D 数组int *参数.这是非法的.要使编译器静音,你必须这样做

    init_2d((int *) a, m, n);
    
    Run Code Online (Sandbox Code Playgroud)

    您的init_2d遗嘱很可能"按预期工作",但仍然没有充分的理由使用这样的黑客.

    这里真正能做的是将2D数组衰减到指向 1D数组的指针.信不信由你,这正是你在print宣言中所做的,即使它没有立即引起注意.您的

    void print(int x, int y, int a[x][y])
    
    Run Code Online (Sandbox Code Playgroud)

    声明实际上相当于

    void print(int x, int y, int (*a)[y])
    
    Run Code Online (Sandbox Code Playgroud)

    宣言.即a实际上是指向类型int [y]的指针 - 指向int大小的1D 数组的指针y.上述两个声明只是表达同一事物的两种表面上不同的方式.

    还要注意,通过"将它们衰减"到任何东西,不需要将2D数组传递给函数.您可以通过指针将2D数组传递给整个2D数组,如

    void print(int x, int y, int (*a)[x][y])
    
    Run Code Online (Sandbox Code Playgroud)

    在这种情况下,要传递数组,您必须使用&运算符

    print(m, n, &a);
    
    Run Code Online (Sandbox Code Playgroud)

    并访问函数内部必须使用*运算符的数组

    printf("%d     ", (*a)[i][j]);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 不,在你的情况下它不可能.指针到指针不能遍历内置的2D数组.顺便说一句,正如您已经在init_2d实现中发现的那样("工作",即使它是非法的),2D数组在内部实现为具有自动2D到1D索引重新计算的一维数组.指向指针不会帮助您遍历这种"平坦"的线性数据.

    当使用完全不同类型的多维数组时,经常使用指针指针类型(或更一般地说,多级指针类型):当N维数组实现为指向独立分配的指针数组时(N-1)维数组.这种多维数组在C程序中也经常使用,但它必须手动实现和管理(你可以在SO上找到很多例子).同时,正如我上面所说,内置语言数组以完全不同的方式实现,并且它们不能被多级指针遍历.