为什么所有数据类型都是2的幂?

时间:2011-03-04 09:21:22

标签: c++ programming-languages

为什么所有数据类型的大小总是2的幂?

我们举两个例子:

short int 16
char 8

他们为什么不跟随?

short int 12

10 个答案:

答案 0 :(得分:11)

这是一个实现细节,并非总是如此。一些奇特的架构具有非二次幂数据类型。例如,36-bit words在一个阶段很常见。

这两天几乎普及的原因是它通常简化了内部硬件实现。作为一个假设的例子(我不做硬件,所以我不得不承认这主要是猜测),操作码的一部分表明它的一个参数可能被存储为两个幂的索引参数中的字节数,因此两个位足以表示参数中的8,16,32或64位中的哪一位,并且将其转换为适当的锁存信号所需的电路将非常简单。

答案 1 :(得分:3)

内置类型是那些大小的原因很简单,这就是CPU本身支持的,即它是最快和最简单的。没有其他原因。

对于结构,你可以在那里有(几乎)任意数量的位的变量,但你通常希望保持整数类型,除非有一个非常紧急的理由不这样做。

您通常还希望将相同大小的类型组合在一起并启动具有最大类型(通常是指针)的结构。
这样可以避免不必要的填充,并确保您没有访问权限一些CPU表现出未对齐的字段(某些CPU甚至可能在未对齐的访问时触发异常,但在这种情况下,编译器会添加填充以避免它,无论如何)。

答案 2 :(得分:3)

char,short,int,long等的大小因平台而异。 32位体系结构往往具有char = 8,short = 16,int = 32,long = 32。 64位体系结构往往具有char = 8,short = 16,int = 32,long = 64。

许多DSP不具备2种类型的功能。例如,摩托罗拉DSP56k(现在有点过时)有24位字。此体系结构的编译器(来自Tasking)具有char = 8,short = 16,int = 24,long = 48。为了使事情变得混乱,他们使char = 24,short = 24,int = 24,long = 48的对齐。这是因为它没有字节寻址:最小可访问单位是24位。当你真的需要访问打包数据数组中的8位字节时,这会产生令人兴奋的(恼人的)属性,涉及大量的除法/模3。

您只会在专用内核中找到非2的2次幂,其大小经过量身定制,以适应特殊的使用模式,从而有利于提高性能和/或功耗。在56k的情况下,这是因为有一个乘加单元可以加载两个24位量,并在3个总线上同时将它们加到48位结果中。整个平台就是围绕它设计的。

大多数通用体系结构使用2的幂的根本原因是因为它们将八位字节(8位字节)标准化为最小大小类型(除了标志)。它没有理由不能成为9位,正如其他地方所指出的那样,24位和36位是常见的。这将渗透到设计的其余部分:如果x86是9位字节,我们有36个八位字节高速缓存行,4608个八位字节页面,569KB对每个人都足够:)我们可能没有&# 39;四位字节'但是,因为你不能将9位字节分成两半。

但现在几乎不可能做到这一点。从一开始就拥有这样设计的系统非常好,但是与8位字节系统生成的数据互操作将是一场噩梦。它已经足够难以解析24位DSP中的8位数据。

答案 3 :(得分:2)

嗯,它们是2的幂,因为它们是8的倍数,而这(通过内存中的原子分配单元通常是一个字节的事实来简化一点)(编辑 :经常(但并非总是)由8位组成。

更大的数据大小一次采用多个字节。 所以你可以有8,16,24,32 ......数据大小。

然后,为了内存访问速度,只有2的幂被用作最小大小的乘数(8),所以你可以得到这些数据的大小:

 8 => 8 * 2^0 bits => char
16 => 8 * 2^1 bits => short int
32 => 8 * 2^2 bits => int
64 => 8 * 2^3 bits => long long int

答案 4 :(得分:1)

8位是一个字节最常见的大小(但不是大小,9位字节和其他字节大小的例子不难找到)。较大的数据类型几乎总是字节大小的倍数,因此它们通常在具有8位字节的系统上为16,32,64,128位,但不总是2的幂,例如2。 24位是DSP常见的,有80位和96位浮点类型。

答案 5 :(得分:0)

标准整数类型的大小被定义为8位的倍数,因为byte是8位(有一些非常罕见的例外),并且CPU的数据总线通常是8的倍数 - 比特宽。

如果你真的需要12位整数,那么你可以在结构(或联合)中使用bit fields,如下所示:

struct mystruct
{
    short int twelveBitInt : 12;
    short int threeBitInt  :  3;
    short int bitFlag      :  1;
};

这在嵌入式/低级环境中非常方便 - 但请记住,结构的整体尺寸仍然可以打包到完整尺寸。

答案 6 :(得分:0)

他们不一定。在某些机器和编译器上,sizeof(long double) == 12(96位)。

答案 7 :(得分:0)

所有数据类型都不必使用2的幂作为代表的位数。例如,long double使用80位(尽管其实现取决于要分配的位数)。

使用2的幂的一个优点是,较大的数据类型可以表示为较小的数据类型。例如,4个字符(每个8位)可以组成一个int(32位)。实际上,一些编译器曾使用两个32位数来模拟64位数字。

答案 8 :(得分:0)

大多数情况下,您的计算机会尝试将所有数据格式保持为整数倍(2,3,4 ...)或整个部分(1 / 2,1 / 3,1 / 4 ......)机器数据大小。它这样做是为了每次加载N个数据字时,它会为您加载整数个信息位。这样,它就不必在以后重新组合部分。

您可以在x86中看到这一点,例如:

char是32位的1/4

短路是32位的1/2

int / long是一个完整的32位

long long是2x 32位

浮点数是一个32位

双倍是32位的两倍

long double可能是32位的三倍或四倍,具体取决于您的编译器设置。这是因为对于32位机器来说,加载96位是三个本机机器字(因此没有开销)。在64位机器上,它是1.5本机机器字,因此128位将更有效(无重组)。 x86上的长双精度的实际数据内容是80位,所以这两个都已填充。

最后一点,计算机并不总是以其原始数据大小加载。它首先获取一个缓存行,然后从本机机器词中读取。缓存行较大,通常约为64或128字节。让一个有意义的数据适合这个并且不会卡在边缘是非常有用的,因为你必须加载两个完整的缓存行来读取它。这就是为什么大多数计算机结构都是两个大小的力量;它将适用于两种尺寸存储的任何功率,无论是一半,完全,两倍还是更多 - 你保证永远不会在边界上。

答案 9 :(得分:0)

在某些情况下,整数类型必须是2的精确幂。如果存在<stdint.h>中的精确宽度类型,例如int16_tuint32_t,则它们的宽度必须恰好是该大小,并且没有填充。声明自己遵循IEEE标准的浮点数学强制floatdouble为2的幂(尽管long double通常不是)。现在,标准库中还有char16_tchar32_t类型,或者C ++内置的类型,定义为精确宽度类型。实际上,有关支持UTF-8的要求意味着charunsigned char的宽度必须恰好是8位。

实际上,在任何不支持宽度恰好为8、16、32和64位的类型的计算机上,很多旧代码已经损坏。例如,任何读取或写入ASCII或尝试连接到网络的程序都会中断。

一些历史上重要的大型机和微型计算机的本机字长是3的倍数,而不是2的幂,尤其是DEC PDP-6,PDP-8和PDP-10。

这是基数8曾经在计算中流行的主要原因:由于每个八进制数字代表3位,因此9位,12位,18位或36位模式可以用八位数字而不是十进制更好地表示或十六进制。例如,当使用base-64将字符打包为6位而不是8位时,每个打包的字符占用两个八进制数字。

当今这些体系结构中最明显的两个遗产是,默认情况下,诸如'\123'之类的字符转义在C语言中被解释为八进制而不是十进制,并且Unix文件权限/掩码被表示为三或四个八进制数字。