为什么初始化一个全局变量,函数的返回值在声明时失败,但在文件范围内工作正常?

一个80k声誉贡献者R ..告诉我,我们不能用函数的返回值初始化全局变量,因为它不被认为是常量,全局变量必须用常量初始化。并且对他的话来说,我是真的按预期得到此程序的以下错误 – initializer element is not a constant是程序:

 #include int foo(); int gvar=foo(); //ERROR int main() { printf("%d",gvar); } int foo() { return 8; } 

但在这种情况下,我只是不明白为什么上面的程序的后续更改版本根本没有显示任何错误并且工作正常。在第二个程序中,我使用相同函数foo()的返回值初始化相同的全局变量foo() 。你能告诉我这种结果变化的严格技术原因是什么?为什么用函数的返回值初始化全局变量会导致错误,但同样的返回值初始化工作正常从一个函数?

 #include int foo(); int gvar; int main() { gvar=foo(); printf("%d",gvar); } int foo() { return 8; } 

输出 8

其背后的原因是,为了确定函数产生的值,需要执行代码,并且在初始化静态和全局变量时,在C中没有执行代码执行。

编译器和链接器协同工作以准备全局内存段的字节映像:编译器提供值,链接器执行其最终布局。 在运行时,段的图像按原样加载到存储器中,无需进一步修改。 这在任何代码执行之前发生,因此不能进行任何函数调用。

请注意,这并不意味着由于某些技术原因而不可能,只有C设计者决定不这样做。 例如,C ++编译器生成一个代码段,该代码段调用全局对象的构造函数,这些代码段在控件传递给main()之前执行。

第二个版本没有gvar的初始化gvargvar在没有初始化器的情况下在全局范围内声明和定义。 它具有静态存储持续时间,因此它初始化为零。

main中的赋值就是:赋值,而不是初始化。

在案例1中,全局变量在声明时赋值变量。

但在第二种情况下,全局变量被赋值( 已经声明 ),返回值为foo()。

数据部分的形成,文本部分都在编译期间发生。

全局变量将在数据部分(bss或初始化数据部分),因此在编译时,foo()不会被调用对吗? 编译时不知道foo()的返回值。

但第二种情况,当文本部分执行时, gvar被赋值为返回值foo()。 这是有效的。

您可以这样想:当main()启动时,所有全局变量必须已经具有初始化值。 正如你所知,它们不能通过调用函数来获取它们,因为main()实际上是在C程序中执行的地方。

我们无法从函数外部调用任何函数。不像shell脚本。函数只允许从函数体内部调用。

在c中,第一次执行从main()开始,编译器不知道函数调用,如果它位于函数外部,它可以作为原型,如果arg和返回类型提供。

我们可以通过从main或其他function块调用函数的返回值,到变量,调用的函数(那个全局)变量。

但我们可以根据需要在全局变量中使用宏。 如:

 #define max() 12 int glob=max(); main() { }