在 C 中分配二维数组的更好做法是什么
what is the better practice to allocate 2d array in C
我正在编写MD模拟程序,其中我需要使用动态分配的二维数组。出于性能原因,我希望二维数组的内存是一个连续的块。我知道有两种方法可以做到这一点
- 在 C99 中使用 VLA。
size_t rows, cols;
int (*arr)[cols] = malloc(sizeof *arr * rows);
if (arr)
{
// do something here
free(arr);
}
- 使用指向指针的指针
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 并且可以完全控制您的实现方式,请使用第一种方法。它在代码方面更简洁,它保证了连续的内存,并且更易于管理。权衡是一些非常粗糙的语法。
我正在编写MD模拟程序,其中我需要使用动态分配的二维数组。出于性能原因,我希望二维数组的内存是一个连续的块。我知道有两种方法可以做到这一点
- 在 C99 中使用 VLA。
size_t rows, cols;
int (*arr)[cols] = malloc(sizeof *arr * rows);
if (arr)
{
// do something here
free(arr);
}
- 使用指向指针的指针
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 并且可以完全控制您的实现方式,请使用第一种方法。它在代码方面更简洁,它保证了连续的内存,并且更易于管理。权衡是一些非常粗糙的语法。