【问题标题】:Magic of casting value to bool将值转换为布尔值的魔法
【发布时间】:2013-06-05 08:21:21
【问题描述】:

今天我意识到将值转换为布尔值是一种魔法:

int value = 0x100;
unsigned char uc = static_cast<unsigned char>(value);
bool b = static_cast<bool>(value);

sizeof(uc)sizeof(b) 都返回 1。我知道uc 将包含0x00,因为只复制了LSB。但是b 将是true,所以我的假设是,当转换为bool 时,值会被评估而不是被复制。

这个假设正确吗?这是标准的 C++ 行为吗?

【问题讨论】:

  • 这是一种黑暗艺术。
  • 一切不是0 都是真的,因为0x100 不是0 ...
  • 我确定这是对其他一些 SO 问题的欺骗,但无论如何,从 C++03 开始​​:“算术、枚举、指针或指向成员类型的指针的右值可以转换为bool 类型的右值。零值、空指针值或空成员指针值转换为 false;任何其他值都转换为 true。"
  • @MichaelBurr 在 SO 上也找不到那个“骗子”。甚至 Google 博士也没有在这里帮助我。
  • 另请注意,严格来说,从intunsigned char 的转换也是“评估”的。评估结果导致 lsb 仅在二进制补码机器上被复制(诚然,这几乎是当今所有的机器)。例如,在 32 位补码机器上,-1 将表示为 0xfffffffe,但转换 unsigned char uc = (unsigned char)(-1); 将导致 uc == 0xff

标签: c++ windows


【解决方案1】:

这并没有什么神奇之处。从intunsigned char 的转换定义为value % 256(对于8 位chars),这就是你得到的。它可以通过复制 LSB 来实现,但您仍然应该从语义上考虑它,而不是实现。

同样,intbool 的转换被定义为 value != 0,这就是你得到的。

[conv.integral][conv.bool] 中的 C++11 标准涵盖了整数(和布尔)转换。对于 C 风格的演员表,请参阅 [expr.cast][expr.static.cast]

【讨论】:

  • 所以你说这是标准的 C++ 行为并且可以安全使用?这是否记录在某处?
  • @WouterHuysentruit 我已经添加了对标准的引用。
【解决方案2】:

它是标准的一部分:

4.12 布尔转换 [conv.bool]

1 算术、无范围枚举、指针或指针的纯右值 to 成员类型可以转换为 bool 类型的纯右值。一个零 值、空指针值或空成员指针值被转换 为假;任何其他值都将转换为 true。类型的prvalue std::nullptr_t 可以转换为 bool 类型的纯右值;这 结果值为假。

【讨论】:

    【解决方案3】:

    是的,当转换为 bool 时,值会被评估,而不是复制。

    其实在你的例子中,只要value不是0b就会是true

    更新:引用 C++ Primer 第 5 版第 2.1.2 章:

    When we assign one of the nonbool arithmetic types to a bool object, the result is false if the value is 0 and true otherwise.

    【讨论】:

      【解决方案4】:

      根据rules for C-style casts(bool)value 实际上是static_cast。然后,static_cast 的第一条规则开始执行,它计算临时“声明和初始化......如new_type Temp(expression);”的值,即bool Temp(value);。这是明确定义的:Temptrue iff value != 0。所以是的,value 在某种意义上被“评估”了。

      【讨论】:

        【解决方案5】:

        转换为bool 是从普通的旧C 继承的功能。最初,C 没有bool 类型,在if 语句中使用其他类型很有用,如下所示:

        int myBool = 1;
        if(myBool) {
            // C didn't have bools, so we had to use ints!
        }
        
        void* p = malloc(sizeof(int));
        if(!p) {
            // malloc failed to allocate memory!
        }
        

        当您转换为 bool 时,它的行为就像您将语句放入 if 中一样。

        当然,C++ 向后兼容 C,所以它采用了这个特性。 C++ 还增加了在你的类上重载转换为bool 的能力。 iostream 这样做是为了指示流何时处于无效状态:

        if(!cout) {
            // Something went horribly wrong with the standard output stream!
        }
        

        【讨论】:

        • 我使用过 C 编译器(如果我没记错的话是 MPLAB),它定义了一个 bool,如:typedef char bool;,所以该编译器上的 bool b = (bool)0x100 肯定会导致 b 成为 false .
        【解决方案6】:

        ISO/IEC C++ 标准:

        4.12 布尔转换 [conv.bool] 1 算术...类型的纯右值可以转换为 bool 类型的纯右值。零值...转换为假;任何其他值都将转换为 true。

        因此,由于 prvalue 是一个值,您可能会说该值得到了评估,尽管这有点自以为是。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-01-24
          • 2016-04-27
          • 2012-02-25
          • 2015-02-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多