记一件有意思的事
写生活日志么?想都别想:)
这件事跟未初始化的非静态局部变量的值有关。
通常,作为一个合格的程序员,定义变量都会给它初始化,特别是非静态的局部变量,使用未初始化的非静态局部变量会发生错误。然而,喵哥今天在看书的时候遇到这么一个奇葩的例子:
#include <bits/stdc++.h>
using namespace std;
int global_init_var = 0;
__attribute__((section("foo"))) int global_uninit_var;
void func1(int i){
printf("%d\n", i);
}
int main(){
static int static_var = 85;
static int static_var2;
int a = 1;
int b; //没有初始化
func1(static_var + static_var2 + a +b);
return 0;
}
看到这代码第一反应就是这代码是不是错了,然后喵哥本着“实践是检验真理的唯一标准”的精神,把上面的代码码了下来,然后跑了一下
我惊了,居然顺利运行过了。本以为由于b没有初始化而得到一个非法的值,但是用GCC跑出来的b老老实实的默认为0。
有点颠覆三观了,跟平时完全不是一回事,然后想到这会不会跟用的编译器有关,我这里用的是GCC。特意去windows用VS跑了一遍,幸好出错了
这是在debug的模式下跑的,b被赋值为0xcccc cccc,并发生异常中断。
如果是release下跑,则不会报异常中断,但是运行结果是错的。
这说明需要要对非静态局部变量初始化不是错觉,平常也需要这么做。
并且,用clang编译得到的结果也是不对的:
那么为什么GCC会给它赋值为0呢,这大概就是底层编译器底层实现的区别了,在网上看到这么一段话:
引自百度知道:gcc局部变量不用初始化么
以 C99 标准为例:
6.7.8/10 未显式初始化的非静态局部变量的值是「不定的」。
3.17.2 「不定的值」是「未指定的值」或「陷阱标识」。
3.17.3 「未指定的值」是该类型有效值,但本国际标准对于具体选择哪个值不作要求。
6.2.6.1/5 对值为「陷阱标识」的对象进行读操作是未定义行为。
所以,这种代码有可能触发未定义行为,能不能跑全靠运气。即便不触发,取值是多少也没有标准保障。
GCC应该是默认把为初始化的整数值初始化为0吧,在喵哥看的那本书中也的确经常提到未初始化与初始化为0 的隐晦关系。比如:
经过初始化的全局变量和静态局部变量会保存在.data处,对于没有初始化的全局变量和静态局部变量则会保存在.bss处,但是如果全局变量和静态局部变量初始化为0的话,则这些全局变量和静态局部变量也会保存在.bss处。
这么说来GCC中对于这个“不定值”的定义可能就是0吧。
2019.07.20
用clang编译的没有初始化的全局变量和静态局部变量和初始化为0的全局变量和静态局部变量也保存在.bss处,所以这个关系跟非静态局部变量初始化为0没啥关系了。。。
上一篇: CSS3 @media的基本用法总结
下一篇: 当前情势下怎样做淘宝客才能赚到钱?