代码之家  ›  专栏  ›  技术社区  ›  Newline

C++到Bool转换的错误

  •  3
  • Newline  · 技术社区  · 7 年前

    bool foo(ObjectType& object){
    
        //code
    
        const float result = object.float_data + object.bool_data * integer_data;
    
        //code
    
    }
    

    我在找虫子的时候发现了 result bool * integer 计算为 255*integer 1*integer .

    布尔 转换为0或1,所以我不明白。我乘 布尔 在代码的其他部分,它工作得很好。而且这是随机的:有时它被转换成 1 ,有时 255 . 调试器还显示 true ,分别是。当这个bug发生时,它总是在执行过程中发生。重新编译代码没有效果,它仍然随机发生。

    4 回复  |  直到 7 年前
        1
  •  1
  •   Max Langhof    7 年前

    你应该检查一下 bool 准备好了。值得注意的是,C++标准确实如此。 保证任何作为 布尔 值将转换为 1 0 -它只保证 布尔 true 将转换为 1个 . 如前所述 here 布尔 拥有一个既不是 真的 也不是 false 由于 . 这可能看起来很明显(毕竟是UB),但也很令人惊讶(显然,即使按照标准作者的标准)。

    这是一个实际的演示,使用 memcpy :

    #pragma pack(1)
    struct ObjectType
    {
        float float_data = -3.0f;
        bool bool_data = false;
        int integer_data = 2;
    };
    
    volatile unsigned char x = 7;
    
    float test()
    {
        // Don't actually do this, it is for demonstration only.
        std::array<unsigned char, sizeof(ObjectType)> data = { 0, 0, 0, 0, /**/ x, /**/ 2, 0, 0, 0 };
    
        ObjectType obj;
        memcpy(&obj, data.data(), sizeof(obj));
    
        return foo(obj);
    }
    

    http://coliru.stacked-crooked.com/a/0221a82a6d35e18b <-运行时计算结果14
    http://coliru.stacked-crooked.com/a/982ff8e4d7503f08

    的确, inspecting the binary 表明 foo 字面上解释 作为整数并与之相乘 gcc 海合会 1个 0个 当它存储到 ,因此表现 真的 只会变成 (只要你不强迫 布尔 真的 ).

        2
  •  4
  •   paxdiablo    7 年前

    C++17 7.14 Boolean conversions ,将非布尔值强制转换为布尔值是标准转换过程的一部分,这意味着在为布尔值指定某些值时,实际上会执行此操作:

    bool . 将零值、空指针值或空成员指针值转换为 false ;任何其他值都转换为 true . 对于直接初始化(11.6),类型为 std::nullptr_t 布尔 ;结果值为

    它是 不要 初始化它,或者将其初始化为非布尔值:

    void someFunction() {
        bool xyzzy;              // Set to some arbitrary value.
        memcpy(&xyzzy, "x", 1);  // Very contrived, wouldn't pass my
                                 //    own code review standards :-)
    }
    

    第一 我要看的是确保你 正确初始化/分配。

    事实上,我非常 很少地 现在,不必显式地将变量初始化为某个东西,就可以将其引入到现实中。即使它在使用前已经更改过,我还是希望编译器能够解决这个问题,并在它认为有用时进行优化。


    但您可以按照预期使用布尔值来解决这个问题。换言之,作为真理的宝库而不是作为整体价值来评价它们。请改为:

    const float result = object.float_data + (object.bool_data ? integer_data : 0);
    

    不管 bool_data 是:

    • 一个不正确初始化的布尔值(尽管您的结果可能是可疑的-我要说的是,您永远不会得到多个 integer_data float_result );或
    • 整数值 治疗
        3
  •  1
  •   Newline    7 年前

    解决了的。bool值没有初始化,因此它有时包含255(rubish)。我假设bool在整数上下文中使用时转换为0或1,而在从值设置时转换为0或1。(这完全是我的错,很抱歉浪费了你的时间。)

    用代码来总结:

    float float_data = 50.0f;
    int integer_data = 30;
    bool bool_data;
    
    float result;
    
    bool_data = 255;                                //OK
    reinterpret_cast<int&>( bool_data) = 250;       //NOT OK
    
    result = float_data + (bool_data ? integer_data : 0);       //OK
    result = float_data + bool_data * integer_data;             //NOT OK.
    result = float_data + !!bool_data * integer_data;           //NOT OK.
    result = float_data + (bool_data == true) * integer_data;   //NOT OK.
    

    “好”,这意味着它仍然是错误的,但至少是0或1

        4
  •  -2
  •   Alan Birtles    7 年前

    bool foo(ObjectType& object){
        //code
        const float result = object.float_data + int(object.bool_data) * int(integer_data);
        //code
    }