在 C 中分配二维数组的更好做法是什么

what is the better practice to allocate 2d array in C

我正在编写MD模拟程序,其中我需要使用动态分配的二维数组。出于性能原因,我希望二维数组的内存是一个连续的块。我知道有两种方法可以做到这一点

  1. 在 C99 中使用 VLA。
size_t rows, cols;
int (*arr)[cols] = malloc(sizeof *arr * rows);
if (arr)
{
  // do something here

  free(arr);
}
  1. 使用指向指针的指针
int **create(int **arr, int rows, int cols)
{
  int nbytes = sizeof(int) * rows * cols;
  int *data = (int *) malloc(nbytes);
  nbytes = sizeof(int *) * rows;
  arr = (int **)malloc(nbytes);
  int n = 0;
  for (int i=0; i <rows; i++){
    arr[i] = &data[n];
    n += cols;
    }
  retrun arr;
 }
void destroy(int **arr)
{
  if (arr == NULL) return;
  free(arr[0]);
  free(arr);
}

我想知道这两个哪个更适合练习,或者还有其他更好的解决方案?对我来说,第一个更简洁,但因为二维数组将被用作参数传递到函数的频率非常高,似乎第二个一个更好。我不是编程专家,所以我想听听您的意见。谢谢

只有第一种方法可以保证内存分配在一个连续的块中。第二种方法不保证行在内存中相邻(很可能不会)。

主要问题是 int (*)[N]int ** 类型不兼容,简单地将一个类型转换为另一个类型不会达到您想要的效果。如果您使用的 API 需要 int **,那么您需要使用第二种方法。

就将每个参数作为参数传递而言,没有实际的性能差异;它们都是指针类型。唯一真正的问题是

void func( size_t cols, size_t rows, int (*arr)[cols] )

可能比

读起来难看一点
void func ( int **arr, size_t rows, size_t cols )

如果您不依赖任何外部 API 并且可以完全控制您的实现方式,请使用第一种方法。它在代码方面更简洁,它保证了连续的内存,并且更易于管理。权衡是一些非常粗糙的语法。