在写C++代码时,有时候可能会忘记对一个布尔变量赋初值,运行程序后会发现产生了一些自己预想不到的结果,或者程序并没有按照设定的分支运行,今天来说一下这背后的原理性的东西。首先来看一段简单代码:
int main()
{
bool bTest;
if (true==bTest)
{
cout << "1" << endl;
}
else if(false==bTest)
{
cout << "2" << endl;
}
else
{
cout << "3" << endl;
}
system("pause");
return 0;
}
在VS中的Debug模式下运行这段代码,会发现输出结果为3;而在Release模式下会发现有的编译器可能输出2,也有可能输出3,而有的编译器可能输出1,也可能输出2。这到底为什么呢?难道布尔类型除了true和false之外还有第三种值?为什么Debug模式和Release模式输出会不一样呢?带着这些疑问来进行进一步深入探索。
首先 有一点需要了解,就是在Debug模式下VC 会把未初始化的栈内存全部填成 0xcccccccc ,当字符串看就是 “烫烫烫烫……”;会把未初始化的堆内存上全部填成 0xcdcdcdcd,当字符串看就是 “屯屯屯屯……”。知道了这一点,先来看Debug模式下的三个实验:
(1)bTest初始化为true;
(2)bTest初始化为false;
(3)bTest未初始化;
根据上述三个实验可以知道,当bool变量初始化为true时,写入内存的是1,当初始化为false是,写入的是0,当未初始化时,写入的是0xcc(十进制是204)。 我们对bool变量赋予不同的初值,反映到内存中就是写入了不同的数值,而true和false只能写入1和0,那如果我们对bool变量不是赋值为true和false,而是用一个数对它赋值,写入内存的又会是什么呢,比如让bTest=12.45,可以看到如下情形:
由实验可知,只要赋值为非零的数值,写入内存的都是1,赋值为零,写入内存的才是0,而对于bool类型变量来说,当你使用这个变量的时候,从内存读取到1,则说明是true,读取到0,则说明是false,而所有非零数据写入内存后都变成1,这样导致读回来其实都是true,这就是大家常说的非零为true,0为false的本质。由此我们可以解释开篇中程序在Debug模式下为什么会输出3呢?因为未对变量初始化,写入内存的是0xcc ,而后面进行比较的时候,读回来发现数值既不是0也不是1而是0xcc,所以既不会等于true,也不会等于false,从而进入程序的else分支。
在Release模式下,并没有会把未初始化的栈内存上全部填成 0xcc的优化,所以当在Release模式下,如果未对bool类型变量进行初始化的话,那么变量的值取决于内存中的原先存储的值,所以输出情况比较随机,既有可能为true,也有可能为false,还可能是一个非true和false的值,而且不同编译器对其优化不一样,导致可能进入的程序分支不同,但基本都是随机的。由此你就可以解释开篇程序在Release模式既有可能输出1又有可能输出2的随机现象呢。