最近在工作中使用gtest时,我收到了一些有趣的错误代码,使我感到奇怪:
error: Expected: b1
Which is: true
To be equal to: b2
Which is: true
这是测试EXPECT_EQ(bool b1, bool b2)
的结果(伪代码)。我做了一些挖掘,这是带有注释的示例代码:
{
bool b1, b2; //uninitialized bool variables
//lets say we are a good programmer
b1 = b2 = true;
if(b1)
if(b2)
if(b1 == b2)
std::cout << "You are a good programmer!" << std::endl;
}
{
bool b1, b2; //uninitialized bool variables
//but we are not always good programmers - b1 and b2 remains uninitialized
auto p1 = reinterpret_cast<unsigned char*>(&b1);
*p1 = 3;
auto p2 = reinterpret_cast<unsigned char*>(&b2);
*p2 = 7;
//code above is a simulation that b1 and b2 contains some trash that was left in the memory
if(b1){
std::cout << "b1 is true. \n";
if(b2){
std::cout << "b2 is true. \n";
if(b1 == b2)
std::cout << "b1 == b2" << std::endl;
else
std::cout << "b1 != b2" << std::endl;
}
}
}
以上代码输出:
You are a good programmer!
b1 is true.
b2 is true.
b1 != b2
首先,这很有意义,您与UB一起玩,就得到了应得的。我知道一个简单的解决方案是“做一个好的程序员,并总是初始化变量”,但是对我来说,显示的行为使调试变得更加困难,因为如果前两个条件是第三个条件,那么无论状态如何,您都希望第三个条件总是成立。布尔变量是否已初始化。用int而不是bool来运行示例代码对我来说非常有意义-如果C ++将0视为false
,将其他任何内容视为true
,则检查if(some_int)
中的int会检查非零数字,然后将它们进行比较会比较实际数字。
但是对于布尔值,我希望比较'功能'仅通过比较字节的最后一位,而不是在255种可能的状态之间进行比较,就只能检查两个状态之间的对与错。
所以我的问题是:
为什么C ++在比较布尔值时比较整个字节,而不是仅包含真/假信息的最后一位。
总而言之:效率。比较两个字节要比比较两个位花费更少的机器代码指令,因为在后一种情况下,需要附加的掩码指令。
请参见关于Godbolt的示例:https://godbolt.org/z/uJ2xXy