在C语言中通过传递指针到函数来创建二维数组

3

我阅读了大量将2D数组指针传递给函数以在函数中获取/更改该数组值的示例。但是是否可能在函数内部创建(分配内存)呢?就像这样:

#include <stdio.h>

void createArr(int** arrPtr, int x, int y);

int main() {

    int x, y;       //Dimension
    int i, j;       //Loop indexes
    int** arr;      //2D array pointer
    arr = NULL;
    x=3;
    y=4;

    createArr(arr, x, y);

    for (i = 0; i < x; ++i) {
        for (j = 0; j < y; ++j) {
            printf("%d\n", arr[i][j]);
        }
        printf("\n");
    }
    _getch();    
}

void createArr(int** arrPtr, int x, int y) {
    int i, j;       //Loop indexes
    arrPtr = malloc(x*sizeof(int*));
    for (i = 0; i < x; ++i)
        arrPtr[i] = malloc(y*sizeof(int));

    for (i = 0; i < x; ++i) {
        for (j = 0; j < y; ++j) {
            arrPtr[i][j] = i + j;
        }
    }    
}

你的代码中没有数组指针,也没有二维数组。 - Lundin
@Martin 你能告诉我怎么做吗? - Marcin
@Lundin 好的,所以有一个指向指针的指针,但它可以用作指向二维数组的指针,对吗? - Marcin
@Marcin 不行,它做不到。这是一个常见的错误,你学习的来源有问题。我会发布一个答案。 - Lundin
3个回答

3

忘记指向指针。它们与二维数组无关。

正确的做法:如何在C中正确设置、访问和释放多维数组?

使用指向指针是错误的原因之一:为什么我需要使用type**来指向type*?

以下是正确的示例:

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


void* create_2D_array (size_t x, size_t y)
{
  int (*array)[y] = malloc( sizeof(int[x][y]) );

  for (size_t i = 0; i < x; ++i) 
  {
    for (size_t j = 0; j < y; ++j) 
    {
      array[i][j] = (int)(i + j);
    }
  }

  return array;
}

void print_2D_array (size_t x, size_t y, int array[x][y])
{
  for (size_t i = 0; i < x; ++i) 
  {
    for (size_t j = 0; j < y; ++j) 
    {
      printf("%d ", array[i][j]);
    }
    printf("\n");
  }
}


int main (void)
{
  size_t x = 5;
  size_t y = 3;

  int (*arr_2D)[y];

  arr_2D = create_2D_array(x, y);

  print_2D_array(x, y, arr_2D);

  free(arr_2D);

  return 0;
}

1
当我尝试使用你的版本时,它会报错: size_t y expression must have constant value。 因此,你不能像这样动态地创建数组(正如我所说的...)。 - Marcin
1
@Marcin 我已经编译并测试了这段代码。你必须使用1999年之后发布的编译器(为什么不呢?)。例如GCC。你可以使用编译器选项 gcc -std=c11 -pedantic-errors 来告诉GCC成为一个C编译器。 - Lundin
今天我花了一整天的时间,但还是无法解决一个问题。你的例子中的所有东西似乎都能正常工作,但我无法解决这个问题。如果我使用函数 print2DArray(xDim, yDim, arr); 打印表格,我可以得到所有元素,所以它可以正常工作。如果我像这样打印一个元素 printf( "%d\n", arr[0][0]) 也可以正常工作。但是,如果我像这样打印 printf( "%d\n",old[1][1]); 或任何其他不为0的值,我会得到分段错误。请帮帮我。 - Marcin
@Marcin,“old”是什么意思? - Lundin
抱歉。 "old" 是我代码中使用的数组名称,但是这里我将其粘贴为“arr”。所以应该是 printf("%d\n", arr[1][1])。在代码中名称是正确的。 - Marcin
显示剩余2条评论

2

是的,传递一个指向int **的指针(但3个星号被认为是不好的风格),我建议从您的函数返回一个分配的变量:

int **createArr(int x, int y)
{
    int **arrPtr;
    int i, j;       //Loop indexes

    arrPtr = malloc(x*sizeof(int*));
    if (arrPtr == NULL) { /* always check the return of malloc */
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    for (i = 0; i < x; ++i) {
        arrPtr[i] = malloc(y*sizeof(int));
        if (arrPtr[i] == NULL) {
            perror("malloc");
            exit(EXIT_FAILURE);
        }
    }
    for (i = 0; i < x; ++i) {
        for (j = 0; j < y; ++j) {
            arrPtr[i][j] = i + j;
        }
    }
    return arrPtr;   
}

使用以下方式进行调用:

arr = createArr(x, y);

2
你应该检查malloc的所有返回值,而不仅仅是第一个。 - mch
1
没有理由创建一个分段指针到指针的东西。 相反,当您想要一个二维数组时,请使用二维数组。 - Lundin
1
@Marcin,看起来很糟糕,因为它确实很糟糕。你一开始就不应该使用任何指向指针的指针。假设你想要的是2D数组,那么你应该使用真正的2D数组。 - Lundin
但是我必须动态创建这个数组(在运行时不知道维度),所以我必须这样做。 - Marcin
@Lundin - 这实际上是我在评论中试图表达的。只要使用[i][j]进行访问,一切都没问题,人们可能认为它与int arr[x][y]相同,但事实并非如此。 - Support Ukraine
显示剩余8条评论

0

是的,可以通过这种方式初始化数组。只要传递指针,内存地址就应该保持不变。因此,如果将任何内容分配给指针,则它将有效。

将a []视为指向第一个元素的a*指针

a [][]将是指向第一个元素的指针或指向第一个数组(表的第一行)的指针的a **指针


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接