欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

记一件有意思的事

程序员文章站 2022-04-06 23:39:30
...

写生活日志么?想都别想:)

这件事跟未初始化的非静态局部变量的值有关。

通常,作为一个合格的程序员,定义变量都会给它初始化,特别是非静态的局部变量,使用未初始化的非静态局部变量会发生错误。然而,喵哥今天在看书的时候遇到这么一个奇葩的例子:

#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没啥关系了。。。

相关标签: C++