16

从C++标准的部分§3.9.1/ 6说,bool类型乐趣未初始化的变量和编译器(GCC)

值可以是truefalse

现在考虑这个代码,

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(),并在main()switch块本身:

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

我只是好奇,想知道为什么在未初始化的布尔行为这突如其来的变化?

好了,从语言的角度很明显:该行为是undefined.I理解。我也明白编译器可以自由地做任何事情。然而,从编译器的角度来看,这对我来说似乎很有意思。什么可以在编译(即GCC)可能在每种情况下,为什么呢?

我使用:g++ (GCC) 4.5.0 - MinGW, on Windows 7 Basic, 64-bit OS

+1

我不能用g ++ - 4.4.5 amd64来复制你的结果。但是如果你想回答自己这类问题,为什么不检查编译器汇编输出? – BatchyX 2011-02-02 19:48:08

回答

17

我只是好奇地想知道为什么这个未初始化布尔行为的突然变化?

拆卸代码,看看编译器的做。

我的猜测:因为值现在只能在本地使用,编译器优化完全它拿走。由于行为不确定,因此编译器可以安全地假设任何值,例如false。这是一个非常明显的优化,因为就编译器而言,b的值是恒定的,并且switch的整个逻辑是多余的。那么为什么把它放在可执行文件中? (这里很重要的一点是,b只能在第二个代码中本地使用,并且反过来也会触发更多的优化,即使在未优化的代码中。第一个代码必须在编译器可以执行任何操作之前进行内联优化或代码路径必须被追踪,这不是微不足道的)。