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


127

在C ++中,

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

为CPU编写仿真器时,我错过了上述内容


10
在C ++中,您可以使用位字段“打包”数据。struct Packed { unsigned int flag1 : 1; unsigned int flag2: 1; };。大多数编译器将分配一个full unsigned int,但是当您进行读/写操作时,它们会自行处理位纠缠。他们还自己处理模运算。这是一个unsigned small : 4属性,其值在0到15之间,当它应该达到16时,它不会覆盖前面的位:)
Matthieu M.

Answers:


208

因为CPU不能寻址小于字节的任何内容。


10
该死的,这
真是

31
实际上,这四个x86指令btbtsbtrbtc 可以解决单位!
fredoverflow 2011年

11
我认为bt寻址一个字节偏移量,然后以给定的偏移量测试该位,无论指定地址时以字节为单位...位偏移量字面量都会有点罗word(打扰)。
user7116 2011年

2
@six:您可以将数组的开头加载到一个寄存器中,然后将相对的“位偏移”加载到第二个寄存器中。位偏移量不限于“一个字节内”,它可以是任何32位数字。
fredoverflow 2011年

4
好吧,是的,不是。我们确实有位域,并且可以有一个位域指针,即地址+位号。显然,由于位数的额外存储要求,此类指针无法转换为void *。
Maxim Egorushkin 2011年

32

维基百科

从历史上看,字节是计算机中用于编码文本的单个字符的位数,因此,它是许多计算机体系结构中的基本可寻址元素

所以字节 基本寻址单元,低于该计算机体系结构无法解决。并且由于(可能)不存在支持4位字节的计算机,因此您没有4位 bool等。

但是,如果您可以设计这样一种体系结构,该体系结构可以将4位作为基本可寻址单元进行寻址,那么bool只有该计算机具有4位的大小!


4
“那么,只有那台计算机上的int大小为4位”-不会,因为标准禁止CHAR_BIT小于8,如果体系结构中的可寻址单元小于8位,则a C ++实现只需要提供一种与基础硬件的内存模型不同的内存模型。
Steve Jessop

@Steve:哎呀...我忽略了这一点。删除intchar从我的职务。
Nawaz

1
您也不能有4位bool,因为C是C ++中char最小的可寻址单元,无论体系结构可以使用其自己的操作码进行寻址。必须具有至少为1的值,并且相邻对象在C ++中必须具有自己的地址,因此实现仅需使其变大并浪费内存。这就是为什么位字段作为特殊情况存在的原因:结构的位字段成员不需要可分别寻址,因此它们可以小于a (尽管整个结构仍然不能)。sizeof(bool)boolchar
史蒂夫·杰索普

// @史蒂夫·杰索普(Steve Jessop):这似乎很有趣。您能否给我从语言规范中得到的参考,其中说它char是C ++中最小的可寻址单元?
Nawaz

3
最接近的特定语句可能是3.9 / 4:“类型T的对象的对象表示形式是由类型T的对象占用的N个无符号字符对象的序列,其中N等于sizeof(T)”。显然sizeof(bool)不能为0.5 :-)我想一个实现可以合法地提供子字节指针作为扩展,但是以普通方式分配的“普通”对象(如bool)必须执行标准所规定的操作。
史蒂夫·杰索普

12

最简单的答案是:这是因为CPU用字节而不是位来寻址内存,并且按位运算非常慢。

但是,可以在C ++中使用位大小分配。位向量有std :: vector专门化,也可以构造采用位大小的条目。


1
不知道我是否同意按位运算速度慢。ands,nots,xor等都非常快。通常是缓慢的按位运算的实现。在机器级别,它们非常快。分支...现在很慢。
霍根

3
为了更清楚一点,如果创建一个布尔向量并将24个布尔放入其中,则它将仅占用3个字节(3 * 8)。如果输入另一个布尔值,它将占用另一个字节。但是,如果您推送另一个布尔值,则不会占用任何额外的字节,因为它使用了最后一个字节中的“空闲”位
Pedro Loureiro

是的,我也怀疑按位操作的速度很慢:)
Pedro Loureiro

位向量不会创建位大小的分配。他们创建字节大小的分配。无法分配单个位。
John Dibling 2011年

1
读取位向量中的单个位需要三个操作:移位和,然后再次移位。写作是两个。单个字节可以访问单个字节。
sukru 2011年

7

在过去的日子里,我不得不在汹涌的暴风雪中上学,双向上山,午餐是我们可以在学校后面的树林中追踪并用裸手杀死的任何动物,计算机的可用内存远少于今天。我曾经使用的第一台计算机具有6K的RAM。不是6兆字节,不是6吉字节,就是6千字节。在这种环境下,将尽可能多的布尔值打包到一个int中是很有意义的,因此我们会定期使用运算将它们取出并放入。

如今,当人们嘲笑您只有1 GB的RAM,而您唯一能找到容量不足200 GB的硬盘的地方是在一家古董店时,打包这些点麻烦就不值得了。


除处理标志外。诸如在某物上设置多个选项之类的东西。00000001 + 00000100 =00000101。–
阿姆斯特朗

@Atomix:我几乎再也没有这样做了。如果需要两个标志,则创建两个布尔字段。我曾经在这样的代码打包的地方写代码,然后写“ if flags&0x110!= 0 then”之类的东西,但是这很神秘,如今,我通常将字段分开写“ if fooFlag || barFlag ”。我不排除出于某些原因而打包这样的标志更好的情况,但是不再需要像以前那样保存内存。
杰伊(Jay)

2
实际上,如果要使计算速度更快,那么打包位非常值得-在存储在内存中的大量数据上。打包布尔值不仅用于较小的存储,这意味着您可以将布尔输入数组的读取速度比解压缩时快8倍(就带宽而言),这通常非常重要。另外,您可以使用位运算,例如popc(填充计数),这可以加快CPU本身的工作速度。
einpoklum

2
如果您每天做大量的布尔运算,则它们是:DBMS,机器学习,科学模拟以及许多其他事情。而且-仅处理它们就意味着将它们复制-从内存到缓存。想想数十亿美元,一百万布尔就算什么了。
einpoklum

1
@PeterCordes是的,绝对是的,如果我有一组布尔逻辑上是“相同的主意”,以便从某种意义上说我自然地将它们视为“数组”,并且然后我要屏蔽或过滤它们,或者否则,对它们执行按位运算,然后将它们打包为字节可能会很有意义。就像我之前说的,我很难想到上次我在一个应用了这些条件的应用程序上工作,但是您给出了几个很好的例子,而且我敢肯定,只要有一点点想象力,其他人就可以想到。
周杰伦

6

您可能有1位布尔值以及4位和2位整数。但这将导致没有性能提升的怪异指令集,因为这是查看架构的不自然方式。实际上,“浪费”字节的更好部分而不是尝试回收未使用的数据实际上是有意义的。

根据我的经验,唯一麻烦将几个布尔值打包到一个字节中的应用程序是Sql Server。


5

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

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

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

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

5

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

但是,如果您有一堆bool,例如,可以使bool以1位为例。在这样的结构中:

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

2

bool可以是一个字节-CPU的最小可寻址大小,或者可以更大。出于性能目的而必须具有bool一定大小的情况并不少见int。如果出于特定目的(例如硬件仿真),您需要一个N位的类型,则可以找到该类型的库(例如,GBL库具有BitSet<N>类)。如果您担心bool(您可能有一个大容器)的大小,那么您可以自己打包或使用std::vector<bool>它来为您做准备(请小心后者,因为它不能满足容器的要求)。


2

考虑一下您将如何在仿真器级别实现此目标...

bool a[10] = {false};

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

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

2

因为通常,CPU会以1字节为基本单位分配内存,尽管某些CPU(如MIPS)使用4字节字。

但是vector交易bool在一个特殊的方式,与vector<bool>每个布尔一位被分配。


1
我相信即使MIPS cpu也会让您访问单个字节,尽管这会降低性能。
Paul Tomblin,

@Paul:是的,您是对的,但通常单词专用lw/ sw的使用更为广泛。
Ryan Li

不了解MIPS,但是IA-64体系结构仅允许在64位边界上进行访问。
Gene Bushuyev 2011年

0

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

更多信息:维基百科


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.