179

在 C++ 中,

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

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

4

13 回答 13

273

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

于 2011-01-07T15:03:42.807 回答
50

来自维基百科

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

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

但是,如果您可以设计这样的架构,可以将 4 位作为基本可寻址单元进行寻址,那么您将bool只有在那台计算机上才有 4 位的大小!

于 2011-01-07T15:18:38.760 回答
19

回到过去,当我不得不在猛烈的暴风雪中步行上学时,双向上坡,午餐是我们可以在学校后面的树林里找到并徒手杀死的任何动物,计算机的可用内存远少于可用的内存。今天。我用过的第一台电脑有 6K 的 RAM。不是 6 MB,不是 6 GB,也不是 6 KB。在那种环境下,将尽可能多的布尔值打包到 int 中是很有意义的,因此我们会定期使用操作将它们取出并放入。

今天,当人们嘲笑你只有 1 GB 的内存时,你唯一能找到小于 200 GB 的硬盘驱动器的地方就是古董店,那就不值得费心去打包了。

于 2011-01-07T17:36:07.493 回答
17

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

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

于 2011-01-07T15:04:42.147 回答
12

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

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

struct A
{
  bool a:1, b:1, c:1, d:1, e:1;
};
于 2011-01-07T15:05:33.990 回答
11

您可以有 1 位布尔值以及 4 位和 2 位整数。但这会产生一个奇怪的指令集,而不会提高性能,因为这是一种不自然的架构方式。实际上,“浪费”一个字节的更好部分而不是试图回收那些未使用的数据是有意义的。

根据我的经验,唯一一个将多个布尔值打包成一个字节的应用程序是 Sql Server。

于 2011-01-07T15:05:08.213 回答
9

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

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
};
于 2011-01-07T15:15:24.703 回答
6

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

于 2011-01-07T16:01:28.823 回答
3

因为一般情况下,CPU 以 1 字节为基本单位分配内存,虽然有些 CPU 像 MIPS 使用 4 字节字。

然而,以一种特殊的方式进行vector交易,为每个布尔分配一个位。boolvector<bool>

于 2011-01-07T15:06:21.853 回答
3

想想你将如何在你的模拟器级别实现它......

bool a[10] = {false};

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

assert(pbool == &rbool);
rbool = true;
assert(*pbool);
*pbool = false;
assert(!rbool);
于 2011-01-07T21:18:20.120 回答
0

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

更多信息:维基百科

于 2011-01-07T15:09:24.600 回答
0

即使可能的最小大小为 1 字节,您也可以在 1 字节上拥有 8 位布尔信息:

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

例如,Julia 语言有 BitArray,我阅读了有关 C++ 实现的信息。

于 2013-01-24T14:16:58.787 回答
0

按位运算并不“慢”。

和/或操作往往很快。

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

CPU 作为部分正确回答的答案通常与读取字节对齐,并且 RAM/内存的设计方式相同。

因此,必须明确订购数据压缩以使用更少的内存空间。

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

于 2021-12-11T18:25:13.467 回答