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

Asm*_*Asm 115 c++ cpu-architecture

在C++中,

  • 为什么布尔1字节而不是1位大小?
  • 为什么不存在类似4位或2位整数的类型?

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

Pau*_*lin 183

因为CPU无法处理小于一个字节的任何内容.

  • 实际上,四个x86指令`bt`,`bts`,`btr`和`btc`*可以*寻址单个位! (25认同)
  • 我认为`bt`解决了一个字节偏移,然后测试给定偏移量的位,无论如何,当指定一个以字节为单位的地址时...位偏移文字将得到*位字*(请原谅双关语). (9认同)
  • 该死的,现在这是尴尬爵士 (8认同)
  • 嗯,是的,不.我们有位域,我们可以有一个位域指针,即地址+位号.显然,由于比特数的额外存储要求,这样的指针不能转换为void*. (3认同)
  • @six:您可以在一个寄存器中加载数组的开头,然后将相对的"位偏移"加载到第二个寄存器中.位偏移不限于"在一个字节内",它可以是任何32位数. (2认同)
  • @gEdringer 如果您试图将尽可能多的信息塞入您可以容纳的子字节字段中,那么总会有位字段。 (2认同)

Naw*_*waz 28

来自维基百科:

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

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

但是,如果你可以设计一个可以将4位作为基本可寻址单元的架构,那么你bool只需要在那台计算机上使用4位大小!

  • "你将拥有大小为4位的int,然后只在那台计算机上" - 不,你不会,因为标准禁止CHAR_BIT小于8.如果架构上的可寻址单元少于8位,那么a C++实现只需要提供一个与底层硬件的内存模型不同的内存模型. (3认同)
  • 你也不能有一个 4 位的“bool”,因为“char”是 C++* 中最小的可寻址单元,无论架构可以用自己的操作码寻址什么。`sizeof(bool)` 的值必须至少为 1,并且相邻的 `bool` 对象必须有自己的地址*在 C++* 中,因此实现只需使它们更大并浪费内存。这就是为什么位字段作为特殊情况存在:结构的位字段成员不需要单独寻址,因此它们可以小于“char”(尽管整个结构仍然不能)。 (2认同)
  • 最接近的特定语句可能是3.9/4:"类型T的对象的对象表示是由类型T的对象占用的N个无符号字符对象的序列,其中N等于sizeof(T)".显然`sizeof(bool)`不能是0.5 :-)我想一个实现可以合法地提供子字节指针作为扩展,但像普通方式分配的像bool这样的"普通"对象必须按标准说的做. (2认同)

suk*_*kru 12

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

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

  • 读取位向量中的单个位需要三个操作:移位,和,再一次移位。写作是两个。而单个字节可以访问单个字节。 (3认同)
  • 不确定我是否同意按位运算很慢。与、非、异或等都非常快。通常是按位运算的实现速度较慢。在机器层面,它们的速度相当快。分支......现在很慢。 (2认同)
  • 为了更清楚,如果你创建一个布尔值向量并将24个布尔值放入其中,它将仅占用3个字节(3*8).如果你输入另一个布尔值,它将需要另一个字节.然而,如果你推另一个布尔值,它将不会占用任何额外的字节,因为它使用最后一个字节中的"空闲"位 (2认同)

bra*_*tao 8

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

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

struct A
{
  bool a:1, b:1, c:1, d:1, e:1;
};
Run Code Online (Sandbox Code Playgroud)


Jay*_*Jay 8

回到过去,我不得不在狂暴的暴风雪中走路上学,两边上坡,午餐是我们可以在学校后面的树林中追踪到的任何动物,用我们的双手杀死,计算机的可用内存比今天.我用的第一台电脑有6K的RAM.不是6兆字节,不是6千兆字节,6千字节.在那种环境中,将尽可能多的布尔值打包到int中是很有意义的,因此我们会定期使用操作将它们取出并放入其中.

今天,当人们嘲笑你只有1 GB的RAM,并且你能找到一个低于200 GB的硬盘的唯一地方就是古董店,那么打包就不值得了.

  • 实际上,如果您希望计算速度更快,那么麻烦打包位是非常值得的 - 在您存储在内存中的大量数据上。打包布尔值不仅适用于较小的存储 - 这意味着您可以比解包时读取布尔输入数组的速度快 8 倍(就带宽而言),这通常非常重要。此外,您可以使用位操作,例如 popc(人口计数),它可以加快您在 CPU 上的工作速度。 (4认同)
  • 如果您这样做,那么您每天都会使用大量的布尔值:DBMS、机器学习、科学模拟以及许多其他事情。并且 - 只是对它们 _working_ 意味着将它们从内存复制到缓存中。一百万布尔不算什么,想想数十亿。 (3认同)
  • 处理标志时除外。诸如在某件事上设置多个选项之类的事情......例如。00000001 + 00000100 = 00000101。 (2认同)

Pau*_*sik 6

你可以有1位bool和4位和2位整数.但这会产生一个奇怪的指令集,没有性能提升,因为这是一种不自然的方式来看待架构.实际上,"浪费"一个字节的更好部分而不是试图回收那些未使用的数据是有意义的.

根据我的经验,唯一困扰将几个bool打包成单个字节的应用程序是Sql Server.


Gen*_*yev 6

bool可以是一个字节——CPU 的最小可寻址大小,也可以更大。bool出于性能目的而必须达到 的大小并不罕见int。如果出于特定目的(例如硬件模拟),您需要 N 位类型,您可以找到一个库(例如 GBL 库有BitSet<N>类)。如果您担心尺寸bool(您可能有一个大容器),那么您可以自己打包,或者使用std::vector<bool>它来为您完成(要小心后者,因为它不满足容器要求)。


Mar*_*ork 5

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

struct X
{
    int   val:4;   // 4 bit int.
};
Run Code Online (Sandbox Code Playgroud)

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

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
};
Run Code Online (Sandbox Code Playgroud)