【问题标题】:Is bool required in C++ to be represented with 1 bit set when true/ 0 bits set when false在 C++ 中是否需要 bool 以在 true 时设置为 1 位/在 false 时设置为 0 位来表示
【发布时间】:2019-08-26 13:50:08
【问题描述】:

我正在考虑通过使用 uint32_t 和 bool[4] 的联合来微优化一个返回 4 个 bool 的函数,然后执行 popcnt 指令来查看 bool 数组中有多少元素为真。

但我不知道标准是否保证 bool 表示为数字,在 true 时只设置 1 位,在 false 时设置 0 位。

如果答案是否定的,那么我有一个后续问题:如果不需要,是否要求表示是恒定的,例如如果我有一个测试来检查转换为 uint_8t 的 true bool 是否为 1(而 false 为 0),这是否意味着程序中 bool 的每个表示都将表现相同。

注意:我知道 bool 不需要为 1byte,但我可以对此进行 static_assert。

【问题讨论】:

  • 我正在考虑通过使用 uint32_t 和 bool[4] 的联合来微优化一个返回 4 个 bool 的函数,然后执行 popcnt 指令来查看 bool 数组的元素数量是的。 为什么不直接使用std::bitset
  • 在 C++ 中,不允许使用联合进行类型双关,这会破坏严格的别名。
  • Casting 不提供任何信息。布尔值转换为 1 (true) 和 0 (false),但这些转换与布尔值的实际表示无关。
  • 一些编译器用无效的bools 做了非常奇怪的事情,所以我不会尝试任何聪明的事情。在此处查看“统一标量”和“无效标量”示例:en.cppreference.com/w/cpp/language/ub

标签: c++ boolean language-lawyer


【解决方案1】:

我正在考虑对返回 4 个布尔值的函数进行微优化 通过使用 uint32_t 和 bool[4] 的联合,然后执行 popcnt 指令查看 bool 数组中有多少元素为真。

这将导致未定义的行为,因为访问联合的非活动成员违反了对象生存期规则。您可能想改用 std::bitset<4> — 它是为这样的使用而设计的。

请注意,std::bitset 不能直接由多个bools 构成,您可能必须先组合一个unsigned long long。或者你可以使用这样的辅助函数:

template <std::size_t N>
constexpr std::bitset<N> pack_bools(const bool (&arr)[N])
{
    static_assert(N <= std::numeric_limits<unsigned long long>::digits);

    unsigned long long num{0};
    for (std::size_t i = 0; i < N; ++i) {
        if (arr[i])
            num += 1LL << i;
    }
    return std::bitset<N>{num};
}

用法:

pack_bools({true, false, true, false}); // for example

(test)

但我不知道标准是否保证 bool 被表示 作为数字,只有 1 位设置为真,0 位设置,当它是 假的。

不,没有这样的保证。 [basic.fundamental]/10:

类型 bool 是具有相同对象的不同类型 表示、价值表示和对齐要求作为 实现定义的无符号整数类型。类型的值 booltruefalse。 [ 注意: 没有signedunsignedshortlong bool 类型或值。 — 结束 注意 ]

没有更多关于价值表示的保证。

如果答案是否定的,那么我有一个后续问题:如果不是 required 是否要求表示是恒定的,例如如果我 进行测试,检查转换为 uint_8t 的 true bool 是否为 1(和 0 for false) 是否意味着布尔的每个表示 该程序的行为将相同。

不,也没有这样的保证。

【讨论】:

  • 我不确定是否违反了对象生命周期规则,因为联合体的两个成员都是 POD,但我可能是错的,因为我的直觉经常是错误的,而且 显然好吧对我来说实际上是UB。
  • “仅此而已。”有点不正确:与例如还定义了指针类型和其他整数类型(即 0/null/nullptr 转换为false,其余转换为true)。当然,这仅指定类型值转换,而不是底层表示。
  • @NoSenseEtAl POD 在生命周期规则方面并不那么重要。是的,有时我们都认为定义明确的不是:)
  • iirc 谈论来自 cppcon 的对象生命周期,一些谷歌人说我们可以使用未初始化的 pod,但也许不能保证它们包含非垃圾值......但是 C++ 再次非常复杂,我不知道想争论这个,因为这不是主要问题,我很确定你是对的。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-07-28
  • 2017-02-21
  • 2019-12-28
  • 2020-08-30
  • 2022-11-23
  • 1970-01-01
  • 2013-04-20
相关资源
最近更新 更多