C:覆盖 Array2D 值在使用函数时不起作用

C: Overwrite Array2D values not working when using function

我想要maxtmp_max的内容。 max 是动态分配的。 tmp_max 尺寸已知。

当我对它进行硬编码时,复制值工作正常,但当我创建一个函数来复制值时,它不起作用。这是为什么?

//This code works
int** max;
init2D(&max,3,4);

int tmp_max[3][4] = {{3,3,2,2}, {1,2,3,4}, {1,3,5,0}};

for(int i = 0 ; i < 3; i++)
    for(int j = 0 ; j < 4; j++)
        max[i][j] = tmp_max[i][j];

assert(max[0][1] == 3); 

//This one crashes
void copyArray2D(int a, int b, int*** tab,int*** tab2){
    for(int i = 0 ; i < a; i++)
        for(int j = 0 ; j < b; j++)
            tab2[i][j] = tab[i][j];
}

int** max;
init2D(&max,3,4);

int tmp_max[3][4] = {{3,3,2,2}, {1,2,3,4}, {1,3,5,0}};
copyArray2D(3,4,&tmp_max,&max); //crash

assert(max[0][1] == 3);

注:

使用 void copyArray2D(int a, int b, int** tab,int** tab2){copyArray2D(3,4,max,tmp_max); 也不起作用。

使用 void copyArray2D(int a, int b, int** tab,int** tab2){copyArray2D(3,4,&max,&tmp_max); 也不起作用。

void init2D(int ***data_ptr, int x, int y) {
    int **data = (int **) malloc(sizeof(int *) * x);
    for (int k = 0; k < x; k++)
        data[k] = (int *) malloc(sizeof(int) * y);
    *data_ptr = data;
}

您的第二个函数的星数过多。当我第一次写答案时你没有显示 init2D 函数,所以我不得不猜测你用它做了什么(但代码现在在问题中并且与我产生的足够接近区别是无关紧要的——除非我对分配进行错误检查)。这是代码的(重写)版本(第一个版本没有接近编译器,我完全错过了一个关键细节)。请注意,int **int arr[N][M] 或主题的变体不同 — 即使您使用相同的符号来访问两者。

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

static void copyArray2D(int a, int b, int **dst, int src[a][b])
{
    for (int i = 0; i < a; i++)
        for (int j = 0; j < b; j++)
            dst[i][j] = src[i][j];
}

static void oom(void)
{
    fprintf(stderr, "Out of memory\n");
    exit(1);
}

static void init2D(int ***arr, int a, int b)
{
    (*arr) = malloc(a * sizeof((*arr)[0]));
    if (*arr == 0)
        oom();
    for (int i = 0; i < a; i++)
    {
        (*arr)[i] = malloc(b * sizeof((*arr)[0][0]));
        if ((*arr)[i] == 0)
            oom();
    }
}

static void dump_2d_array(int a, int b, int arr[a][b])
{
    for (int i = 0; i < a; i++)
    {
        for (int j = 0; j < b; j++)
            printf(" %2d", arr[i][j]);
        putchar('\n');
    }
}

static void dump_2d_pointers(int a, int b, int **arr)
{
    for (int i = 0; i < a; i++)
    {
        for (int j = 0; j < b; j++)
            printf(" %2d", arr[i][j]);
        putchar('\n');
    }
}

int main(void)
{
    int **max;
    init2D(&max, 3, 4);

    int tmp_max[3][4] = { { 3, 3, 2, 2 }, { 1, 2, 3, 4 }, { 1, 3, 5, 0 } };
    copyArray2D(3, 4, max, tmp_max);
    printf("2D array:\n");
    dump_2d_array(3, 4, tmp_max);
    printf("List of pointers:\n");
    dump_2d_pointers(3, 4, max);
    return 0;
}

运行 代码的输出:

2D array:
  3  3  2  2
  1  2  3  4
  1  3  5  0
List of pointers:
  3  3  2  2
  1  2  3  4
  1  3  5  0

请注意,我没有写自由函数,所以内存泄漏了。

警惕3-Star Programming

void copyArray2D(int a, int b, int tab[a][b],int*** tab2){
    for(int i = 0 ; i < a; i++)
        for(int j = 0 ; j < b; j++)
            (*tab2)[i][j] = tab[i][j];
}

copyArray2D(3,4,tmp_max,&max);

您的编译器应该会抱怨 copyArray2D(3,4,&tmp_max,&max)

在尝试 运行 您的代码之前,您必须解决编译器发现的任何问题(运行基于损坏的代码编译任何此类可执行文件是没有意义的)。

一个问题是 copyArray2D 在应该说 int** 的时候说 int***

修复后,这里的主要问题是您编写了 copyArray2D,因此它仅适用于指针数组。 (您正在通过分配一个指针数组来模拟二维数组,然后使每个指针指向代表每一行的单独分配)。

这在您使用 init2D 时有效,因为 init2D 函数分配了一个指针数组等

然而 int tmp_max[3][4] 是一个包含 12 个连续整数的块。没有指针。这与 copyArray2D.

不兼容

您的选择是:

  • 使用int **tmp_max并使用init2D分配,而不是int tmp_max[3][4]
  • 制作另一个版本的 copyArray2D,它适用于连续的二维数组。
  • 使用丑陋的宏