在C中为二维数组分配内存的最佳方法是什么?

Jar*_*vis 2 c malloc double-pointer multidimensional-array

什么是分配内存以一个最好的方式two-d arrayC,从两个观点:memory-managementspeed

另外,哪个更好用,a two-d array(并为其分配内存)或double pointer?有人可以详细解释一下,内部会发生什么,为什么一种方法比另一种更好?

Lun*_*din 11

为了获得最佳性能和最佳可读性,应始终将此类数组分配为连续的内存块:

type (*array) [X][Y] = malloc( sizeof(type[X][Y]) );
Run Code Online (Sandbox Code Playgroud)

你应该避免这个:

// BAD METHOD, not a real array

type** lookup_table = malloc( X*sizeof(type*) );
for(size_t i=0; i<Y; i++)
{
  lookup_table[i] = malloc( Y*sizeof(type) );
}
Run Code Online (Sandbox Code Playgroud)

由于种种原因,前者更快.它被分配在一个连续的内存块中,而不是在整个堆中进行分段.分段版本阻止了所有形式的代码优化和高效的片上数据缓存使用,而且实际分配也慢得多.

上面的"坏"版本有一个优点,那就是当您希望单个维度具有可变长度时,例如在为字符串创建查找表时.然后你必须使用那个表格.但是如果你想要一个真正的2D阵列,那么就没有理由不使用前者.


请注意,第一个版本通常写为

type (*array) [Y] = malloc( sizeof(type[X][Y]) );
Run Code Online (Sandbox Code Playgroud)

允许更方便的使用:array[i][j],而不是可读性较低(*array)[i][j].


Sto*_*ica 5

data_type (*mat)[size_2] = malloc(size_1 * size_2 * sizeof(data_type));
Run Code Online (Sandbox Code Playgroud)

这将为一个数组("2d数组")分配连续的内存.如果你不需要荒谬的1个空间,这就是你要走的路.您将减少内存碎片,提高缓存友好性并避免因使用而导致过多的开销malloc.


1 对于一些(特定于应用程序)的荒谬定义

  • 关于VLA,情况并非100%明确.是的,如果您按字面意思阅读标准,如果`mat`是VLA,我的版本应该调用UB.但是,我们中的一些人认为该标准在这方面措辞严厉.没有理由你必须*取消引用指针*以获得VLA的尺寸.实现必须携带某种类型的元数据才能使VLA工作 - 没有理由相信它在评估`sizeof`时不能只使用那些元数据. (2认同)