【问题标题】:8 bool vs 1 int8 个布尔值与 1 个整数
【发布时间】:2012-08-31 02:12:31
【问题描述】:

bool 在 C++ 中占用 1 个字节。但是,为什么 bool[8] 占用 8 个字节而不是 1 个字节? 一个字节有足够的空间容纳 8 位。

我使用 GCC 使用 -Os 标志编译了这个:

#include <iostream>

using namespace std;

class Foo
{
    public:
        bool m_bool[8];
};

int main ()
{
    cout << "Size: " << sizeof(Foo) << " byte(s) " << endl;

   return 0;
}

它返回“大小:8 字节”。

有办法优化吗?

【问题讨论】:

  • 如果你需要大小,你可以使用bitset。不过,使用 1 位宽度比仅使用普通数据类型要慢。
  • 一个布尔值在 C++ 中不占用 1 位,只有一个向量 可以提供这种压缩。
  • 在 C/C++ 中,任何对象都不能小于 1 字节。将它们放在一个数组中不会“神奇地”压缩它们。
  • 我也认为 bool 的大小不需要为 1 字节 - 试图找到它
  • @nhahtdh 确实如此。很多人讨厌vector&lt;bool&gt;,因为它破坏了与向量行为的几个一致性。老实说,我只见过一种情况,它最终比deque&lt;bool&gt; 更快。

标签: c++ sizeof


【解决方案1】:

编译器必须允许您获取各个布尔值的地址,例如

Foo foo;
bool* p = &foo.m_bool[0];
bool* q = &foo.m_bool[1];

如果布尔值被打包,p 和 q 会是什么?

【讨论】:

  • 如果标准委员会想要疯狂,他们可以将 bool* 定义为特殊的,类似于成员函数指针。然后它将是一个包含指向字节的指针和位偏移量的结构。
  • @ZanLynx 这会使标准混乱很多,因为char 基本上被定义为最小指针步幅,CHAR_BITS &gt;= 8 必须保持不变。您必须为位引入一个单独的指针类型才能实现这一点。
  • @Rhymoid 打印错误,sizeof(char) = 1 定义。
  • @Rhymoid:布尔的单独指针类型正是我的评论所在。我确实说过这将是一个疯狂的想法。
  • @Rhymoid:如果指针类型是指向类成员的指针,那么用户对指针类型的所有了解IS都是错误的。看? C++已经有疯狂的指针类型了。
【解决方案2】:

首先 bool 的大小不能保证为 1。其次,当您将 8 个组合在一起时,为什么您仍然希望结果为 1?

8 x 1 = 8

【讨论】:

  • 1 字节 = 8 位。如果编译器使用每个布尔值 1 位应该是可能的。
  • 错误 - 字节不要求为 8 位。这就是为什么我们有宏 CHAR_BIT
  • 哦!好的。我不知道 CHAR_BIT 宏。在这种情况下,CHAR_BIT 是 8。但是,一个字节是 8 位,一个 'char' 是 CHAR_BIT 位。
  • 没有一个字节是一个字节 CRAY 的我认为使用了 10 位字节 - 一直到 CPU 拱门。 char==byte 但如果不是强制的,则为大小。字节不是技术定义的术语。
  • 你是对的。我在这里进行了研究,发现了 IEEE 1541-2002。正如您所说,它定义了“字节”术语,但没有定义大小。我真的不知道。
【解决方案3】:

由于我在上面的cmets中没有看到它,所以我将提一个概念来回应“有没有办法优化它?”如果你还没有使用它。它被称为 bitmasking,您基本上使用 int 作为一系列位,并使用 bitwise 运算符来评估整数中的各个位。

为了方便地适当地设置字符串中的位,通常定义一些在语义上命名的常量并设置为 2 的幂的值(这样它们只会“翻转”一位。您可以轻松地使用bitshift 操作符,以明确哪个位被翻转:

#define IS_ADMIN = 1<<0;
#defing CLEAR_CACHE = 1<<1;

然后你像这样测试管理员:

if(userSettings & IS_ADMIN) { ...

这是一个起点wiki article

【讨论】:

  • 我从未尝试过,但我怀疑现代英特尔处理器上的位旋转比仅仅存储一个过大的 int 值要慢 - 特别是使用 64 位寄存器 - 测试 bool 它仍然需要一个 64 位寄存器
  • 我认为,当您开始一次比较多个位时,真正的收获就来了,例如,如果存在 3 个不同位中的任何一个(认为权限)将表明一个“真实”的案例您的业​​务规则。
  • 可能在那种情况下。我被我在工作中处理的一些位域困住了,它们是排序的“标志”,它们的长度在 1-4 位之间变化——最初它们存储在 32 位中,因为我们通过卫星馈送传输了这些数据。今天,它增加了不必要的复杂性和计算能力来解码它们,因为我们所有的客户端都有至少 100Mb 的连接,并且从那时起我的数据速率呈指数增长 ;-)
  • @AdrianCornish:Bit twiddling 不是很耗时或很慢。位移或掩码比加法更简单,需要 1 个周期。串联的两个或三个非相关位操作也可能需要... 1 个周期。相比之下,英特尔 Nehalem 上的 L1 高速缓存访​​问是 4 个周期。如果您可以将两个数据项打包在一个字节中,那么您在访问主 RAM、网络或磁盘存储时的速度就会提高一倍。
【解决方案4】:

“有办法优化吗?”

您确定优化会有益吗?您可以使用枚举作为标志而不是布尔值,将它们全部存储在一个字节中。

How to use enums as flags in C++?

【讨论】:

    【解决方案5】:

    有办法优化吗?

    您可以使用所谓的bit-field 来做到这一点。位域值不能有其地址。

    【讨论】:

      猜你喜欢
      • 2014-02-13
      • 2011-07-30
      • 2017-12-30
      • 2011-11-05
      • 2013-09-14
      • 2011-05-02
      • 1970-01-01
      • 1970-01-01
      • 2017-04-08
      相关资源
      最近更新 更多