在C中制作二维数组的最佳方法是什么

Ter*_*rry 2 c declaration definition multidimensional-array variable-length-array

我想用C语言制作一个二维数组。

我知道一种方法可以做到这样。

#include <stdlib.h>

void    my_func(int **arr)
{
        printf("test2: %d\n", arr[0][1]);
}

int     main(void)
{
        const int row = 3;
        const int col = 4;

        int **arr = (int **)malloc(sizeof(int *) * 3);
        arr[0] = (int *)malloc(sizeof(int) * 4);
        arr[1] = (int *)malloc(sizeof(int) * 4);
        arr[2] = (int *)malloc(sizeof(int) * 4);

        arr[0][0] = 1;
        arr[0][1] = 2;
        arr[0][2] = 3;
        arr[0][3] = 4;
        arr[1][0] = 3;
        arr[1][1] = 4;
        arr[1][2] = 5;
        arr[1][3] = 6;
        arr[2][0] = 5;
        arr[2][1] = 6;
        arr[2][2] = 7;
        arr[2][3] = 8;

        printf("test1: %d\n", arr[0][1]);

        my_func(arr);

}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,数组可以作为参数传递给函数。但它并不那么漂亮。如果数组有很多值(例如 20*20),我需要逐行键入每个值。

所以我搜索了一下,发现了一种制作这样的数组的方法。

#include <stdio.h>

void    my_func(int **arr)
{
        printf("test2: %d", arr[0][1]);
}

int     main(void)
{
        const int row = 3;
        const int col = 4;

        int arr[row][col] = {
                {1,2,3,4},
                {3,4,5,6},
                {5,6,7,8}
        };
        printf("test1: %d", arr[0][1]);

        my_func(arr);
}
Run Code Online (Sandbox Code Playgroud)

它很简洁,不会让我疲惫不堪。但是当数组传递给函数时出现了问题。并且编译时出现如下警告

test_2D_array.c:20:11: warning: incompatible pointer types passing 'int [3][4]' to
      parameter of type 'int **' [-Wincompatible-pointer-types]
                my_func(arr);
                        ^~~
test_2D_array.c:3:20: note: passing argument to parameter 'arr' here
void    my_func(int **arr)
                      ^
1 warning generated.
Run Code Online (Sandbox Code Playgroud)

即使该函数也无法访问数组参数。存在分段错误。

所以我想知道制作数组的最佳方法,该数组可以作为参数传递给任何函数,并且比我的第一个代码更省力。

感谢您的阅读。

Vla*_*cow 5

int **arr = (int **)malloc(sizeof(int *) * 3);
Run Code Online (Sandbox Code Playgroud)

不是二维数组的声明或分配

int *这里创建了一个具有元素类型的一维数组。然后一维数组的每个元素依次指向一个分配的一维数组,其元素类型为int

这个二维数组的声明

    const int row = 3;
    const int col = 4;

    int arr[row][col] = {
            {1,2,3,4},
            {3,4,5,6},
            {5,6,7,8}
    };
Run Code Online (Sandbox Code Playgroud)

是不正确的。可变长度数组(并且您声明了可变长度数组)可能不会在声明中初始化。

你可以写

    enum { row = 3, col = 4 };

    int arr[row][col] = {
            {1,2,3,4},
            {3,4,5,6},
            {5,6,7,8}
    };
Run Code Online (Sandbox Code Playgroud)

当这样的数组传递给函数时,它会隐式转换为指向该类型的第一个元素的指针int ( * )[col]

您可以通过以下方式将其传递给具有可变长度数组类型参数的函数

void    my_func( size_t row, size_t col, int arr[row][col] )
{
        printf("test2: %d", arr[0][1]);
}
Run Code Online (Sandbox Code Playgroud)

或者是否将枚举的定义放在函数声明之前

    enum { row = 3, col = 4 };
Run Code Online (Sandbox Code Playgroud)

那么该函数也可以声明为

void    my_func( int arr[][col], size_t row )
{
        printf("test2: %d", arr[0][1]);
}
Run Code Online (Sandbox Code Playgroud)

这是一个演示程序,展示了三种不同的方法。第一个是使用数组大小​​的编译时常量定义数组时。第二个是创建可变长度数组时。第三种是动态分配指向一维数组的指针的一维数组。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum { row = 3, col = 4 };

void output1( int a[][col], size_t row )
{
    for ( size_t i = 0; i < row; i++ )
    {
        for ( size_t j = 0; j < col; j++ )
        {
            printf( "%d ", a[i][j] );
        }
        putchar( '\n' );
    }
}

void output2( size_t row, size_t col, int a[row][col] )
{
    for ( size_t i = 0; i < row; i++ )
    {
        for ( size_t j = 0; j < col; j++ )
        {
            printf( "%d ", a[i][j] );
        }
        putchar( '\n' );
    }
}

void output3( int **a, size_t row, size_t col )
{
    for ( size_t i = 0; i < row; i++ )
    {
        for ( size_t j = 0; j < col; j++ )
        {
            printf( "%d ", a[i][j] );
        }
        putchar( '\n' );
    }
}


int     main(void)
{
        int arr1[row][col] = 
        {
                {1,2,3,4},
                {3,4,5,6},
                {5,6,7,8}
        };

        output1( arr1, row );
        putchar( '\n' );

        const size_t row = 3, col = 4;

        int arr2[row][col];

        memcpy( arr2, arr1, row * col * sizeof( int ) );

        output2( row, col, arr2 );
        putchar( '\n' );

        int **arr3 = malloc( row * sizeof( int * ) );

        for ( size_t i = 0; i < row; i++ )
        {
            arr3[i] = malloc( col * sizeof( int ) );
            memcpy( arr3[i], arr1[i], col * sizeof( int ) );
        }

        output3( arr3, row, col );
        putchar( '\n' );

        for ( size_t i = 0; i < row; i++ )
        {
            free( arr3[i] );
        }

        free( arr3 );
} 
Run Code Online (Sandbox Code Playgroud)

程序输出是

1 2 3 4 
3 4 5 6 
5 6 7 8 

1 2 3 4 
3 4 5 6 
5 6 7 8 

1 2 3 4 
3 4 5 6 
5 6 7 8 
Run Code Online (Sandbox Code Playgroud)

请注意,该函数output2可以与数组arr1一起使用,就像与数组一起使用一样arr2