为什么我们总是将常量声明为2的幂?

问题描述 投票:10回答:9

我在其他代码中看到的大多数常数都是2的幂,即

#define SIZE 256

要么

public static final int SIZE = 2048;

是否有任何特殊原因我们这样做而不是

#define SIZE 257

?

constants bit-manipulation
9个回答
29
投票

2的幂是方便的,因为它们很好地映射到硬件中的底层约束。

如:

  1. 页面大小
  2. 地址空间限制
  3. 对齐constaints(一般是DWORD或QWORD对齐,两个幂都是2)

对于标志,2的幂始终具有单个位集。所以像MY_FLAG_1 | MY_FLAG_2 | MY_FLAG_3 | ...这样的东西只能使用2的幂。同样用&测试标志。

对于缓冲区大小等,它也可以选择最接近的2的较大功率。


18
投票

一个很好的理由是bitmasking。例如,如果使用常量来表示对象(或其他任何东西)的属性,则可以通过位掩码将许多属性保存到单个整数中,并在以后标识各个属性。非常适合在数据库中保存许多“标志”。


4
投票

内存通常以操作系统的页面大小的倍数分配,并且在许多情况下,排列事物以准确地适合页面(为了不浪费内存)是有用的。这取决于具体的分配例程,这是否真的有帮助;例如如果有一个隐式标题,那么大小为2的幂实际上可能会受到伤害。


2
投票

当谈到阵列大小时,我怀疑有两个原因可以解释为什么两个人的权力受到青睐。其中一个 - 正如这里的几个回复所证明的那样 - 那些不知道“幕后”发生了什么的程序员似乎普遍认为使用2的幂可能会更有效。另一个是(现在主要是历史)与循环缓冲区有关。

使用掩码可以在读取和写入索引(或指针)上更容易和更快地处理2的幂的循环缓冲区,而不是使用通常较慢的模运算或使用需要分支的条件。这在旧机器上至关重要,但对于传输大量数据仍然很重要 - 例如图形处理

例如,在C中,可以通过以下方式获得可在循环缓冲区中读取的字节数:

pending = (SIZE + wr - rd) & (SIZE - 1);

如果不使用2的幂,那么等价物将是:

pending = (SIZE + wr - rd) % (SIZE - 1);

在没有实现除法/模数指令的机器上,很少“%”可能需要几百个周期,所以你需要这样的东西:

if (wr >= rd)
    pending = wr - rd;
else
    pending = (SIZE + wr) - rd;

这会使代码混乱并导致分支,从而导致指令流失。

写入缓冲区就像是

buf[wr++] = x;
if (wr == SIZE)
    rd = 0;

成为(通常)更有效:

buf[wr++] = x;
wr &= SIZE-1;

当然,如果您使用无符号8位变量来索引256个条目数组,那么您甚至不需要进行屏蔽。


2
投票

我们的变量大小是2(1,2,4或8字节)的幂。计算机在这些边界上工作很舒服。在过去,我们习惯于仔细填充结构以使代码更快,有时使指针算法更容易。

如果您可以选择256到257之间的大小,那么我们选择256.一个原因是调试。当您查看内存或文件时,调试器或hex文件查看器将以2的幂为单位显示数据。

这是一个显示每行16个字节的组,每组4个。

alt text (来源:wikimedia.org

对于标志,我们使它们的幂为2,因此我们可以在一个变量中分别处理它们,而不是在许多变量或数组中。

所以他们都可以或者来自同一个变量。

bits |= 8;       //00000100
bits |= 32;      //00010000

//bits is now 40   00010100

bits &= 32;      //00010000

//bits is now 32   00010000

许多程序员会用十六进制而不是十进制来编写数字,这样就可以更容易地看到单个位发生了什么。


1
投票

没有太多理由真的。由于结构化和堆栈中的变量对齐,三个字节的数组可能在内存中占用4或8个字节。我认为这感觉很好。

由于堆内部结构的开销,从堆中分配整数页可能无法有效地工作。分配4096字节(32位Windows机器的1页)可能导致分配4104字节或更多。

如果常量是标志,则故事非常不同。具有位标志通常比某些基数中不是2的幂的标志更有效。


1
投票

使用二进制计算机,可以方便地使用基于标准的binary multiples,如Mebibyte(或Kibi,Gibi,Tebi ......)。这些2个数字的力量在OctalHex符号中看起来也不错。


1
投票

通常通过将芯片上的“单元”数量增加四倍来向存储器芯片添加更多位。两倍宽,两倍长,四倍的记忆(除了“细胞”之间的较小距离)。

此外,使用单个移位比使用添加连续移位的通用复制算法更容易,这取决于是否设置了特定位。 OpenGL因需要两种尺寸的纹理来访问特定的扫描线而闻名。


-2
投票

因为计算机内存与0/1是二进制系统一起工作。

© www.soinside.com 2019 - 2024. All rights reserved.