c - 我们如何使用一个 malloc 语句分配一个二维数组

标签 c

我在一次采访中被问到如何分配一个二维数组,下面是我的解决方案。

#include <stdlib.h>

int **array;
array = malloc(nrows * sizeof(int *));

for(i = 0; i < nrows; i++)
{
    array[i] = malloc(ncolumns * sizeof(int));
    if(array[i] == NULL)
    {
        fprintf(stderr, "out of memory\n");
        exit or return
    }
}

我认为我做得很好,但后来他要求我使用一个 malloc() 语句而不是两个。我不知道如何实现它。

任何人都可以建议我在单个 malloc() 中完成它的想法吗?

最佳答案

只需计算 nrows 行指针和实际数据所需的内存总量,将其全部加起来,然后执行一次调用:

int **array = malloc(nrows * sizeof *array + (nrows * (ncolumns * sizeof **array));

如果您认为这看起来太复杂,您可以将其拆分并通过命名大小表达式的不同术语使其有点 self 记录:

int **array; /* Declare this first so we can use it with sizeof. */
const size_t row_pointers_bytes = nrows * sizeof *array;
const size_t row_elements_bytes = ncolumns * sizeof **array;
array = malloc(row_pointers_bytes + nrows * row_elements_bytes);

然后您需要遍历并初始化行指针,以便每一行的指针指向该特定行的第一个元素:

size_t i;
int * const data = array + nrows;
for(i = 0; i < nrows; i++)
  array[i] = data + i * ncolumns;

请注意,生成的结构与您使用的结构略有不同,例如int array[nrows][ncolumns],因为我们有明确的行指针,这意味着对于像这样分配的数组,没有真正要求所有行都具有相同数量的列。

这也意味着像 array[2][3] 这样的访问与对实际二维数组的类似访问不同。在这种情况下,最里面的访问首先发生,array[2]array 中的第 3 个元素读取指针。然后将该指针作为(列)数组的基础,我们在其中进行索引以获取第四个元素。

相反,对于类似的东西

int array2[4][3];

这是一个“打包”的正确二维数组,仅占用 12 个整数的空间,像 array[3][2] 这样的访问简单地分解为向基地址添加一个偏移量获取元素。

关于c - 我们如何使用一个 malloc 语句分配一个二维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8740195/

相关文章:

连接两个 32 位数字以获得 64 位结果

编译自定义 malloc

c++ - gcc/g++ : "No such file or directory"

c - 事先声明的功能

C:将数组值初始化为零的问题

c - 仅使用 X11 lib 在 C 中截取窗口的屏幕截图

c - 如何读取/写入二维数组形式的二进制文件?

c++ - OpenSSL 配置最大连接数

c - 为什么这个 C 代码在没有 cygwin 的情况下可以在 linux 上运行,但不能在 Windows 上运行

c++ - 同步屏幕 I/O & pthread & C++