C:为什么在2的幂中分配字符串长度?

时间:2018-01-13 00:33:15

标签: c arrays string memory

为什么C程序员经常以2的幂分配字符串(char数组)?

你经常看到......

char str[100]
char str[500]
char str[2000]

不太经常,你看......

char str[384]

为什么?

我理解答案将涉及以二进制方式处理的内存...但为什么我们不经常看到{{1}},即128 + 256(两个的倍数)。

为什么两个倍数未使用?为什么C程序员使用两个 powers

4 个答案:

答案 0 :(得分:8)

除了一些非常罕见的情况外,没有充分的理由。

揭穿最常见的论点:它有助于内存分配器避免碎片。

大多数情况下它不会。如果你分配 - 比方说 - 256字节,内存分配器将为它的内部管理和内务管理添加一些额外的空间。所以你的分配在内部更大。两个256缓冲区的大小与512字节缓冲区相同?不对。

对于性能,它甚至可能会造成伤害,因为CPU缓存的工作方式。

假设您需要N个某种大小的缓冲区,您可以这样声明它们:

char buffer[N][256];

现在每个buffer[0]buffer[N-1]在其地址中具有相同的最低有效位,这些位用于分配缓存行。缓冲区的第一个字节都占用CPU缓存中的相同位置。

如果你一遍又一遍地计算每个缓冲区的前几个字节,你就不会从第一级缓存中看到太多加速。

另一方面,如果您将这样声明:

char buffer[N][300];

各个缓冲区在地址中没有相同的最低有效位,并且第一级缓存可以完全使用它。

很多人已经遇到过这个问题,例如在这里看到这个问题:Matrix multiplication: Small difference in matrix size, large difference in timings

对于两个二进制缓冲区大小,有一些合法的用例。例如,如果您编写自己的内存分配器,则希望以大小等于操作系统页面大小的方式管理原始内存。或者你可能有硬件约束迫使你使用两个幂数(GPU纹理等)。

答案 1 :(得分:7)

一个有趣的问题。 OS内存管理使用Buddy内存分配技术时,大小为2 ^ k的块更适合。这种技术处理分配的碎片。 https://en.wikipedia.org/wiki/Buddy_memory_allocation

此分配系统将块大小与2的大小对齐。但这用于堆分配。

int * array = (int*) malloc(sizeof(int)*512); // OS manages heap memory allocation

在堆栈上分配缓冲区时,不需要进行块对齐。

int buffer[512]; // stack allocation

我认为没有理由将权力的大小设为2。

答案 2 :(得分:2)

这是为了最小化微小的内存块数量,这些内存太小而无法用于任何事情,但在程序分配或释放内存时需要走路。来自Joel Spolsky’s blog的经典解释,一直追溯到2001年:

  

智能程序员通过始终分配大小为2的内存块来最小化malloc的潜在破坏。你知道,4个字节,8个字节,16个字节,18446744073709551616个字节等。由于任何使用乐高的人都应该直观的原因,这可以最大限度地减少自由链中发生的奇怪碎片的数量。虽然看起来这似乎浪费了空间,但也很容易看出它永远不会浪费超过50%的空间。所以你的程序使用的内存不会超过它需要的两倍,这不是什么大不了的事。

此前还有很多关于内存堆实现的讨论,包括Donald Knuth在计算机编程艺术中的讨论。不是每个人都一定会同意这个建议,但这就是人们这样做的原因。

答案 3 :(得分:1)

系统本身使用2的幂来设置各种限制。例如,文件名长度的最大分配可以是256或32768.磁盘页面大小是2的幂等。

我们经常要记住这些系统限制,并使用2的相同权力。

但是如果你只需要257个字节,不要过度分配512个字节。一些程序员使用2的幂来设置用户输入的限制。这可能会使用户感到困惑。它在旧计算机中有一些好处,但现在不行。

其他时候我们使用随机分配的分配。例如,我们可能使用1000或1024来读取一行文本,因为我们不知道输入的时间长度。无论如何,这都是糟糕的编程。在这种情况下,如果分配为1000或1024,这无关紧要。