C++ 标准第 §3.9.1/6 节说,
bool 类型的值为
或true
。false
现在考虑这段代码,
void f(bool b)
{
switch(b) //since b is bool, it's value can be either true or false!
{
case true: cout << "possible value - true"; break;
case false: cout << "possible value - false"; break;
default: cout << "impossible value";
}
}
int main()
{
bool b; //note : b is uninitialized
f(b);
return 0;
}
编译
F:\workplace>g++ test.cpp -pedantic
跑。输出:
不可能的价值
意外的输出?嗯,事实并非如此,正如标准在 §3.9.1/6 的脚注中所述:
因此,无论我编译并运行该程序多少次,我都会得到相同的输出:按照描述的方式使用布尔值 按照本国际标准 “未定义”,例如 通过检查某个值 未初始化自动对象, 可能会导致它表现得像 不真实也不虚假。
impossible value
。但是,如果我稍微改变一下 - 从图片中删除函数
f()
,并在
switch
本身中写入
main()
块:
int main()
{
bool b; //note : b is uninitialized
switch(b) //since b is bool, it's value can be either true or false!
{
case true: cout << "possible value - true"; break;
case false: cout << "possible value - false"; break;
default: cout << "impossible value";
}
return 0;
}
然后我编译并运行这个程序,我没有得到
impossible value
作为输出;无论我重复多少次,我都不会明白
impossible value
。我只是想知道为什么未初始化 bool 的行为会突然发生变化?
嗯,从语言的角度来看,很明显:行为是未定义的。我理解这一点。我也明白编译器可以自由地做任何事情。然而,从编译器的角度来看,这对我来说似乎非常有趣。
编译器(即 GCC)在每种情况下可能会做什么?为什么?
我正在使用:g++ (GCC) 4.5.0 - MinGW, on Windows 7 Basic, 64-bit OS
。
我只是想知道为什么未初始化 bool 的行为会突然发生变化?反汇编代码,看看编译器在做什么。
我的猜测:由于该值现在仅在本地使用,因此编译器将其完全优化掉。由于行为无论如何都是未定义的,编译器可以安全地假设任何值,例如
false
。这是一个非常明显的优化,因为就编译器而言,
b
的值是恒定的,并且
switch
的整个逻辑是多余的。那么为什么要把它放在可执行文件中呢?(这里重要的一点是,
b
仅在第二个代码中本地使用,即使在未优化的代码中,这反过来也会触发更多的优化。第一个代码必须先内联,然后编译器才能进行任何此类优化,或者必须跟踪代码路径,这并不简单)。
我有一些代码可以归结为
if(!(a == b && c.d())) { do_something(); }
我一直在追寻的 bug 是
do_something()
错误地发生了。 然而
a
绝对等于
b
并且
c.d()
看起来返回 true。当我追踪这个问题时,我临时添加了这些测试打印输出:
if( a == b && c.d() ) printf("yes\n"; else printf("no\n");
if(!(a == b && c.d())) printf("noo\n"; else printf("yess\n");
令我惊讶的是,这打印了
yes
和
noo
,这既证实了为什么
do_something
发生,也证实了正在发生一些非常奇怪的事情。事实证明方法
d()
类似于
bool whatever::d() {
return _successful;
}
但是
_successful
未初始化。 当我打印出它的值时,它是 236,这就是为什么我之前说过“
c.d()
似乎返回 true。”我没有检查汇编代码,但我猜测在某些情况下,gcc正在测试它是否非零,但在其他情况下,它只是测试低位。
正确初始化
_successful
使错误消失。 (自从早期的程序员首次编写方法
d()
以来,它已经有十年没有初始化了。然而,直到几个月前,这个错误才显现出来。这就是为什么有时,软件很难。)