还君明珠刘松仁版:关于gcc全局变量初始化
来源:百度文库 编辑:九乡新闻网 时间:2024/04/29 08:56:18
今天无意中发现,如下代码在gcc下编译报错,感觉很奇怪。很好奇gcc如何初始化全局变量的。代码: int i = 10;
main()
{
static int j = i;
}
这样程序在gcc下编译就会出问题,但相同的代码在vc 6.0下没有任何问题。
但如果把代码改为:
int i = 10;
main()
{
static int j = 0;
j = i;
}
这样就没有问题了。
于是网上发帖求教。 解释如下: 解释者:kiffa 在C++中对于以下语句:
// 全局域
int i = 3;
int j = i;
编译时将i 放入.data 段,设置其值为3.
而对于j ,编译器遇到这种语句,只知道j = i ,由于 i 是变量,不是常量,编译器无法在编译时直接得到它的值,编译器只会找到i 的地址, 然后读取这个地址的内容,再把这个内容写入 j 的地址。
编译器不能够直接用3 来初始化 j ,因为计算机不是人,不懂简单的人类逻辑,我们想“因为 i = 3,而 j = i,所以j = 3",而计算机无法在逻辑上由i = 3 和 j = i 来推出j = 3,就好像图灵机不可能证明某个论题的真伪一样。
计算机只会“取 i 的地址,把3 放到 i 的地址中,取 i 的地址,读取这个地址中的内容,取 j 的地址,把这个内容 写入j 的地址。” 它不会思考,不懂因果,只是机械地执行指令。编译器无法在编译时求得一个非常量的值,它只能在运行时通过读取变量地址来间接得到变量的值,而全局变量在编译时就必须确定其值,故C有静态存储区数据必须用常量初始化的规定。
在编译时只能用常量去初始化一个静态存储区的数据,而不能用“读取某个变量的内容”来初始化,所以编译器会将j 放入 .bss段,默认值为0 ,然后添加一条语句在运行时读取i 的值,再赋给j。这条语句在调用main()之前完成。 一个对比:
对于语句:
int i = 3
int main()
{
int j = i;
...
}
在编译时不需要确定局部变量 j 的值,而是在运行时读取i 的值来赋给 j. 编译连接后的可执行文件中不会存放j 的值,只有相应的赋值语句的代码。与此相对的,由于i 是全局变量,存储在静态存储区,因此在编译时其值就需要确定其值,在目标文件中会分配空间来存放 i 的值,运行时不会有赋值语句来给 i 赋值, 没有对应的代码。
而对于语句:
int i = 3;
int j = i;
由于j 是全局变量,存储在静态存储区,因此也需要在编译时确定其值。而i 是变量,不是常量,i 的值无法在编译时确定,这就造成j 的值也无法在编译时确定,所以C对此就会报错。而C++采取了另外一种做法,在编译时简单的把 j 作为未初始化的全局变量放入.bss 区,其默认值为0,然后添加一条语句在运行时给 j 赋值,并保证这条语句在 main函数开始之前执行。因此j 的初始化实际上实在运行时完成的。
main()
{
static int j = i;
}
这样程序在gcc下编译就会出问题,但相同的代码在vc 6.0下没有任何问题。
但如果把代码改为:
int i = 10;
main()
{
static int j = 0;
j = i;
}
这样就没有问题了。
于是网上发帖求教。 解释如下: 解释者:kiffa 在C++中对于以下语句:
// 全局域
int i = 3;
int j = i;
编译时将i 放入.data 段,设置其值为3.
而对于j ,编译器遇到这种语句,只知道j = i ,由于 i 是变量,不是常量,编译器无法在编译时直接得到它的值,编译器只会找到i 的地址, 然后读取这个地址的内容,再把这个内容写入 j 的地址。
编译器不能够直接用3 来初始化 j ,因为计算机不是人,不懂简单的人类逻辑,我们想“因为 i = 3,而 j = i,所以j = 3",而计算机无法在逻辑上由i = 3 和 j = i 来推出j = 3,就好像图灵机不可能证明某个论题的真伪一样。
计算机只会“取 i 的地址,把3 放到 i 的地址中,取 i 的地址,读取这个地址中的内容,取 j 的地址,把这个内容 写入j 的地址。” 它不会思考,不懂因果,只是机械地执行指令。编译器无法在编译时求得一个非常量的值,它只能在运行时通过读取变量地址来间接得到变量的值,而全局变量在编译时就必须确定其值,故C有静态存储区数据必须用常量初始化的规定。
在编译时只能用常量去初始化一个静态存储区的数据,而不能用“读取某个变量的内容”来初始化,所以编译器会将j 放入 .bss段,默认值为0 ,然后添加一条语句在运行时读取i 的值,再赋给j。这条语句在调用main()之前完成。 一个对比:
对于语句:
int i = 3
int main()
{
int j = i;
...
}
在编译时不需要确定局部变量 j 的值,而是在运行时读取i 的值来赋给 j. 编译连接后的可执行文件中不会存放j 的值,只有相应的赋值语句的代码。与此相对的,由于i 是全局变量,存储在静态存储区,因此在编译时其值就需要确定其值,在目标文件中会分配空间来存放 i 的值,运行时不会有赋值语句来给 i 赋值, 没有对应的代码。
而对于语句:
int i = 3;
int j = i;
由于j 是全局变量,存储在静态存储区,因此也需要在编译时确定其值。而i 是变量,不是常量,i 的值无法在编译时确定,这就造成j 的值也无法在编译时确定,所以C对此就会报错。而C++采取了另外一种做法,在编译时简单的把 j 作为未初始化的全局变量放入.bss 区,其默认值为0,然后添加一条语句在运行时给 j 赋值,并保证这条语句在 main函数开始之前执行。因此j 的初始化实际上实在运行时完成的。
关于gcc全局变量初始化
C C++全局变量初始化 initializer element is not constant 错误 c++中为什么不能对全局变量在函数外赋值
关于模式和初始化向量IV
瓢虫 >> gcc
gcc 汇编
一篇关于GCC的转载的文章 很好。。。。 - 黑客安全,软件教程,新闻资讯 - 中国黑客技...
word初始化
Android--全局变量 很好很强大
GCC的扩展语法
ARMv7 - GCC Wiki
gcc 参数详解
GCC使用详解(1) -
gcc编译C++程序
gcc 优化选项
GCC常用参数
gcc使用手册1
gcc命令行详解
电脑速度初始化
载体初始化会
驱动的初始化
Java对象初始化顺序
GCC内嵌汇编进阶
gcc中的内嵌汇编语言
用gcc编译C++程序