关闭

关于C/C++中全局变量的初始化问题的深入思考

发表于:2012-10-25 09:57

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:yang_yulei    来源:51Testing软件测试网采编

  前言:

  前日,在一次C++课程上,刘老师在举例说明构造函数和析构函数的功能时,提到了全局变量初始化时的构造函数的行为。构造函数在main函数之前初始化全局变量。当然在C++下我是深信不疑的。但随后老师声称C语言下的全局变量也是如此,因为C没有构造和析构函数,所以我们无法看到这一过程,在C++下可以在构造和析构函数中向屏幕打印信息,进而可以观察全局变量的初始化和生存期。

  这个观点无疑使我心头一震,作为C的痴迷者,长期以来在我头脑中的印象是,全局变量在编译期就完成初始化了。难道我的观念是错误的?!难道C真的也是在main函数之前,在程序运行初期才初始化?!

  于是我翻看了《C语言参考手册》这本书上没有明确的答案,再翻看著名的K&R的《C程序设计语言》中只有括号里面的一句话“在概念上.......”也是含糊其辞。(现在想想这个问题可能和编译器有关,所以丹爷爷也没说明太多)

  在网上查询了一下,关于这个问题,持什么观点的都有,没有一个权威的答案。

  只能靠自己了,动手实验!

  先给出我的结论:

  C和C++中的一般全局变量(不包括类class)是在编译期确定的初始值,而不是在程序运行时,在main函数之前初始化的。

  C++中的类的全局变量是在程序运行时,在main函数之前初始化的。

  预热知识:

  C或者C++语言,明面上的入口函数是main(argc,argv),或者tmain、wmain、WinMain等等。但实际上,是C Runtime的startup代码中的void mainCRTStartup(void)函数,调用了编程者写的main函数。这个函数定义在VisualC++安装目录的crt\src\目录下的某个.c文件中(视VC++的版本不同,存放的文件也不同)。它在执行一些初始化操作,如获取命令行参数、获取环境变量值、初始化全局变量、初始化io的所需各项准备之后,调用main(argc,argv)。main函数返回后,mainCRTStartup还需要调用全局变量的析构函数或者atexit()所登记的一些函数。往深里说,是在链接生成可执行文件时,告诉链接器这个可执行文件的entry就是mainCRTStartup。当然,我们也可以对编译器进行设置,使其不插入mainCRTStartup函数代码

  以VC++6.0为例设置:Project->Settings->Link 在Category中选择Output,在Entry-point symbol中填上main 即可。

  -------------------------

  实验一:

  1、C语言环境下:

  实验准备:

int a ;
int main(void)
{
       return a+3 ;
}

  在编译器中设置入口函数为main(具体方法见上面)

  这样,我们让编译器生成的程序,直接从main函数中进入,而不是先执行mainCRTStartup函数做一些准备工作

  结果预测:

  这样,如果函数返回的是3,则说明此全局变量是在编译期就被初始化为0了,如果函数返回的是其它数字,则说明此全局变量是在程序运行时,main函数运行前进行的初始化。

  实验结果:

  进入控制台(运行cmd命令),运行编译后的程序(因为程序没有向屏幕输出结果,我们看不到任何现象),继续输入命令:echo  %ERRORLEVEL% 则显示3,此即为函数的返回值。

  (echo是显示其后的值,系统把前面运行的程序的返回值放在%ERRORLEVEL%中,故我们可以通过此方法获得主函数的返回值)

31/3123>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号