9

80k声誉贡献者R..在SO 上告诉我,我们不能用函数的返回值初始化全局变量,因为这不被认为是常量,全局变量必须用常量初始化。他的话是真的,我明白了正如预期的那样,该程序出现以下错误 - 。这initializer element is not a constant是程序:

#include<stdio.h>
int foo();
int gvar=foo();  //ERROR

int main()
{
printf("%d",gvar);
}

int foo()
{
 return 8;
}

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

#include<stdio.h>
int foo();
int gvar;

int main()
{
gvar=foo();
printf("%d",gvar);
}

int foo()
{
return 8;
}

输出 8

4

5 回答 5

15

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

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

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

于 2013-05-03T08:38:57.487 回答
3

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

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

于 2013-05-03T08:41:07.660 回答
1

在情况 1 中,全局变量在声明时被分配了一个变量。

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

数据段、文本段的形成都发生在编译过程中。

全局变量将在数据部分(bss 或初始化的数据部分)中,所以在编译时, foo() 不会被调用,对吗?并且 foo() 的返回值在编译期间是未知的。

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

于 2013-05-03T08:38:04.737 回答
0

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

于 2013-05-03T09:44:05.180 回答
0

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

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

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

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

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

}
于 2016-05-27T05:46:15.660 回答