C ++-布尔到int转换错误

时间:2018-08-20 09:18:59

标签: c++ gcc c++17

我的代码中有一个看起来像这样的函数:

bool foo(ObjectType& object){

    //code

    const float result = object.float_data + object.bool_data * integer_data;

    //code

}

寻找错误时,我发现result有时值不正确,原因是有时bool * integer的计算方式是255*integer而不是{{ 1}}。

C ++表示在整数上下文中,1*integer被转换为零或一,所以我不明白这一点。我在代码的其他部分乘以bool,效果很好。这也是随机的:有时会转换为bool,有时会转换为1。调试器还分别显示255true。当此错误发生时,它总是在执行过程中发生。重新编译代码没有任何效果,但仍然会随机发生。

4 个答案:

答案 0 :(得分:3)

根据C++17 7.14 Boolean conversions,将非布尔值强制转换为布尔值是标准转换过程的一部分,这意味着在将某些值分配给布尔值时实际上已完成:

  

算术,无作用域枚举,指针或指向成员类型的指针的prvalue可以转换为bool类型的prvalue。零值,空指针值或空成员指针值将转换为false;其他任何值都将转换为true。对于直接初始化(11.6),可以将类型std::nullptr_t的prvalue转换为类型bool的prvalue。结果值为false

例如,如果您初始化布尔值或以如下方式初始化布尔值,则保证布尔值将为零或一它被视为非布尔值:

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)。或
  • 将整数值处理为布尔值(尽管无论如何这都是一个坏主意)。

答案 1 :(得分:1)

已解决。布尔值未初始化,因此有时其中有255(红)。我假设在整数上下文中使用布尔值时会将其转换为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

答案 2 :(得分:1)

您应该检查bool的设置位置。值得注意的是,C ++标准不会保证如果内存不完全为bool,则任何以1值访问的内存都将转换为0-它仅保证值bool的{​​{1}}将转换为true。如here所述,由于未定义行为1可能具有既不是bool也不是true的值。这可能看起来很明显(毕竟是UB),但也令人惊讶(显然,即使按标准作者的标准)。

以下是使用false的实际演示:

memcpy

http://coliru.stacked-crooked.com/a/0221a82a6d35e18b <-运行时评估得出14
http://coliru.stacked-crooked.com/a/982ff8e4d7503f08 <-编译时评估得出2

实际上,inspecting the binary表明#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); } 确实将foo解释为整数,并与bool相乘。我会得出结论,gcc通过仅在存储到gcc时才存储10来实现标准一致性,从而表现就好像 bool仅会转换为true(只要您绝不强迫1进入与booltrue不同的状态)。

答案 3 :(得分:-2)

我认为您应该使用以下代码然后执行它

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