为什么布尔值是1字节而不是1位?

在c++中,

  • 为什么布尔值是1字节而不是1位?
  • 为什么没有4位或2位整数类型?

在为CPU编写模拟器时,我忽略了上述内容

89997 次浏览

因为CPU不能寻址任何小于字节的东西。

最简单的答案是;这是因为CPU以字节而不是位来寻址内存,按位的操作非常慢。

然而,在c++中可以使用位分配。对于位向量,有std::vector专门化,还有接受位大小条目的结构。

你可以有1位的bool型和4位和2位的int型。但这将导致一个奇怪的指令集,没有性能提升,因为这是一种不自然的方式来看待体系结构。“浪费”一个字节的大部分,而不是试图回收未使用的数据,实际上是有意义的。

根据我的经验,唯一一个把几个bool包进一个字节的应用程序是Sql Server。

因为字节是语言中最小的可寻址单位。

但是你可以让bool取1位作为例子,如果你有一堆 如。在结构体中,像这样:

struct A
{
bool a:1, b:1, c:1, d:1, e:1;
};

因为在一般情况下,CPU以1字节作为基本单位分配内存,尽管一些CPU如MIPS使用4字节字。

然而,vector以一种特殊的方式处理bool,为每个分配的bool值分配一个vector<bool>位。

字节是计算机中数字数据存储的较小单位。在计算机中,RAM有数百万个字节,每个字节都有一个地址。如果每个比特都有一个地址,那么计算机就可以少管理8倍的内存。

更多信息:维基百科

您可以使用位字段来获取子大小的整数。

struct X
{
int   val:4;   // 4 bit int.
};

尽管它通常用于将结构映射到精确的硬件预期位模式:

// 1 byte value (on a system where 8 bits is a byte)
struct SomThing
{
int   p1:4;   // 4 bit field
int   p2:3;   // 3 bit field
int   p3:1;   // 1 bit
};

维基百科:

历史上,字节是的个数 用于编码单个字符的位 电脑里的文本,的确如此 因此基本可寻址 元素在许多计算机中 架构。< / p >

因此字节是 基本可寻址单元,低于这个值计算机体系结构无法寻址。由于(可能)不存在支持4位字节的计算机,所以没有4比特 bool等。

然而,如果你可以设计这样一个架构,它可以将4位寻址作为基本可寻址单元,那么你将只有4位大小的bool,并且只在那台计算机上!

bool可以是一个字节——CPU的最小可寻址大小,也可以更大。出于性能考虑,将bool设置为int的大小是很正常的。如果出于特定目的(比如硬件模拟),你需要一个N位的类型,你可以找到一个库(例如GBL库有BitSet<N>类)。如果你关心bool的大小(你可能有一个大容器),那么你可以自己打包位,或者使用std::vector<bool>来为你做这件事(要小心后者,因为它不满足容器的要求)。

在过去,我不得不在肆虐的暴风雪中步行上学,一路上都要上坡路,午餐是我们在学校后面的树林里找到的任何动物,然后徒手杀死,当时电脑的可用内存比现在少得多。我用过的第一台电脑有6K的内存。不是6mb,不是6gb,是6kb。在那种环境下,将尽可能多的布尔值打包到一个int型中是很有意义的,因此我们会经常使用操作将它们取出并放入。

今天,当人们嘲笑你只有1gb的RAM,而你唯一能找到小于200gb的硬盘的地方是在古董店,它只是不值得麻烦打包比特。

考虑一下如何在模拟器级别实现这一点……

bool a[10] = {false};


bool &rbool = a[3];
bool *pbool = a + 3;


assert(pbool == &rbool);
rbool = true;
assert(*pbool);
*pbool = false;
assert(!rbool);

即使最小大小可能是1字节,你可以在1字节上有8位布尔信息:

http://en.wikipedia.org/wiki/Bit_array

Julia语言有BitArray,我读过c++实现。

位操作并不“慢”。

和/或操作往往很快。

问题是对齐和解决它的简单问题。

cpu作为部分正确回答的答案通常与读取字节对齐,RAM/内存也以同样的方式设计。

因此,为了使用更少的内存空间,必须显式地对数据压缩进行排序。

正如一个回答所建议的,您可以为结构中的每个值指定特定的位数。然而,如果CPU/内存没有对齐,之后会做什么呢?这将导致未对齐的内存,而不是+1或+2或+4,如果你想在一个值中使用一半大小的位,则没有+1.5,等等,因此无论如何都必须填充或将剩余空间还原为空白,然后只需读取下一个对齐的空间,它至少以1对齐,通常默认以4(32位)或8(64位)对齐。CPU通常会抓取包含标志的字节值或int值,然后检查或设置所需的标志。所以你仍然必须将内存定义为int, short, byte或适当的大小,但是当访问和设置值时,你可以显式地压缩数据并将这些标记存储在该值中以节省空间;但是很多人不知道它是如何工作的,或者当他们有开/关值或标记当前值时跳过这一步,即使在发送/recv内存中节省空间在移动和其他受限的环境中非常有用。在将int型数据分割为字节的情况下,它没有什么价值,因为你可以单独定义字节(例如int 4Bytes;vsbyte1;字节Byte3;在这种情况下,使用int是多余的;然而,在虚拟环境中,更容易像Java,他们可能定义大多数类型为int(数字,布尔等),因此在这种情况下,你可以利用一个int划分它,并使用字节/位为一个超高效的应用程序,必须发送更少的整数数据(4对齐)。因为它可以说是冗余管理位,然而,它是许多优化之一,位操作是优越的,但并不总是需要;很多时候,人们通过将布尔值存储为整数来利用高内存限制,并浪费500%-1000%左右的内存空间。它仍然很容易有它的用途,如果你在其他优化中使用它,那么在运行和其他数据流中,只有字节或几kb的数据流,如果总体上你优化了所有内容,无论它是否会加载,或加载速度快,在这种情况下,所以减少发送的字节数最终会让你受益匪浅;即使你可以在每天的互联网连接或应用程序中发送大量不需要发送的数据。这绝对是你为移动用户设计应用程序时应该做的事情,甚至是现在大公司应用程序失败的事情;使用过多的空间和加载限制,可能是一半或更低。不做任何事情和堆积在未知的包/插件之间的区别,这些包/插件在加载前至少需要数百KB或1MB,而设计的速度需要1KB或几KB,这将使它加载和行动更快,因为你会遇到那些有数据限制的用户和人,即使对你来说加载浪费的MB或数千KB的不需要的数据也很快。