我的代码中有一个看起来像这样的函数:
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
。调试器还分别显示255
或true
。当此错误发生时,它总是在执行过程中发生。重新编译代码没有任何效果,但仍然会随机发生。
答案 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
时才存储1
或0
来实现标准一致性,从而表现就好像 bool
仅会转换为true
(只要您绝不强迫1
进入与bool
或true
不同的状态)。
答案 3 :(得分:-2)
我认为您应该使用以下代码然后执行它
bool foo(ObjectType& object){
//code
const float result = object.float_data + int(object.bool_data) * int(integer_data);
//code
}