C/C++ 的全局变量初始化与不初始化的区别

在C语言里,全局变量如果不初始化的话,默认为0,也就是说在全局空间里:

int x =0; 跟 int x; 的效果看起来是一样的。但其实这里面的差别很大,强烈建议大家所有的全局变量都要初始化,

他们的主要差别如下:


编译器在编译的时候针对这两种情况会产生两种符号放在目标文件的符号表中,对于初始化的,叫强符号,未初始化的,

叫弱符号。

连接器在连接目标文件的时候,如果遇到两个重名符号,会有以下处理规则:

1、如果有多个重名的强符号,则报错。

2、如果有一个强符号,多个弱符号,则以强符号为准。

3、如果没有强符号,但有多个重名的弱符号,则任选一个弱符号。


基于以上规则看下面的程序:(编译器为gcc 3.4.6, VC下结果不一样)

main.cpp


int x;

void foo();
int main(int argc, char* argv[])
{
printf("x1:%d\n", x);
foo();
printf("x2:%d\n", x);
return 0;
}

var.cpp


int x;
void foo()

{
x = 2;
}

因为两个文件里面的x都被初始化了,所以编译出来的两个目标文件里x都是强符号,连接的时候会报错:

multiple definition of `x' 

符合规则1。

把var.cpp里面的int x = 0;改成 int x; 不做初始化,编译、连接无任何警告,运行结果为:

x:1

x:2

说明连接的时候以main.cpp中的x为准,foo函数修改的是main.cpp中定义的x。符合规则2。

把main.cpp中的初始化也去掉,改成 int x; 编译、连接仍然很顺利,运行结果为:

x:1

x:2

说明main函数和foo函数修改的是同一个x,连接器自己选择了一个x,符合规则3.

大部分情况下,我们不希望连接器为我们做决定,所以我不是很认同后两个规则,至少应该给个警告,而不应该安静地通过。

也许写var.cpp的人根本不知道main.cpp里面也有一个x呢,foo函数的本意也许并不是要修改main.cpp中的x。因为这种问题引起的bug会很难查。

所以我们要尽量把全局变量初始化,对于不想给别的文件引用的变量,也尽量用static修饰。


除了连接时的表现不一样外,未初始化的符号在目标文件的bss段中,而初始化的符号在data段中。


bss段(未手动初始化的数据)并不给该段的数据分配空间,只是记录数据所需空间的大小。
data(已手动初始化的数据)段则为数据分配空间,数据保存在目标文件中。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值