社区
C语言
帖子详情
C语言 全局变量、static变量为什么初始值为零?
zsyqdr
2009-09-04 10:25:56
C语言 全局变量、static变量为什么初始值为零?
别告诉我说:这是c语言规定的,我知道规定是这样。
我想知道其中的原理,或者说在系统中怎么就实现了定义一个全局变量,系统就给他初始化为零了?
我要的是知道其中的道理。。。望高人指点。。。
...全文
1562
7
打赏
收藏
C语言 全局变量、static变量为什么初始值为零?
C语言 全局变量、static变量为什么初始值为零? 别告诉我说:这是c语言规定的,我知道规定是这样。 我想知道其中的原理,或者说在系统中怎么就实现了定义一个全局变量,系统就给他初始化为零了? 我要的是知道其中的道理。。。望高人指点。。。
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
7 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
baihacker
2009-09-04
打赏
举报
回复
楼主自己矛盾了,一会儿问为什么是零,一会儿又问怎么实现。
至于实现定义变量要看编译原理了。
下面文章说明了谁在负责初始化。
下面文章的来源:
http://hi.baidu.com/b5000/blog/item/b4f9138291e123a10df4d243.html
C运行时库详解2007-12-14 21:15
运行时库是程序在运行时所需要的库文件,通常运行时库是以LIB或DLL形式提供的。C运行时库诞生于20世纪70年代,当时的程序世界还很单纯,应用程序都是单线程的,多任务或多线程机制在此时还属于新观念。所以这个时期的C运行时库都是单线程的。
随着操作系统多线程技术的发展,最初的C运行时库无法满足程序的需求,出现了严重的问题。C运行时库使用了多个全局变量(例如errno)和静态变量,这可能在多线程程序中引起冲突。假设两个线程都同时设置errno,其结果是后设置的errno会将先前的覆盖,用户得不到正确的错误信息。
因此,Visual C++提供了两种版本的C运行时库。一个版本供单线程应用程序调用,另一个版本供多线程应用程序调用。多线程运行时库与单线程运行时库有两个重大差别:
(1)类似errno的全局变量,每个线程单独设置一个;
这样从每个线程中可以获取正确的错误信息。
(2)多线程库中的数据结构以同步机制加以保护。
这样可以避免访问时候的冲突。
Visual C++提供的多线程运行时库又分为静态链接库和动态链接库两类,而每一类运行时库又可再分为debug版和release版,因此Visual C++共提供了6个运行时库。如下表:
C运行时库 库文件
Single thread(static link) libc.lib
Debug single thread(static link) libcd.lib
MultiThread(static link) libcmt.lib
Debug multiThread(static link) libcmtd.lib
MultiThread(dynamic link) msvert.lib
Debug multiThread(dynamic link) msvertd.lib
2.C运行时库的作用
C运行时库除了给我们提供必要的库函数调用(如memcpy、printf、malloc等)之外,它提供的另一个最重要的功能是为应用程序添加启动函数。
C运行时库启动函数的主要功能为进行程序的初始化,对全局变量进行赋初值,加载用户程序的入口函数。
不采用宽字符集的控制台程序的入口点为mainCRTStartup(void)。下面我们以该函数为例来分析运行时库究竟为我们添加了怎样的入口程序。这个函数在crt0.c中被定义,下列的代码经过了笔者的整理和简化:
void mainCRTStartup(void)
{
int mainret;
/*获得WIN32完整的版本信息*/
_osver = GetVersion();
_winminor = (_osver >> 8) & 0x00FF ;
_winmajor = _osver & 0x00FF ;
_winver = (_winmajor << 8) + _winminor;
_osver = (_osver >> 16) & 0x00FFFF ;
_ioinit(); /* initialize lowio */
/* 获得命令行信息 */
_acmdln = (char *) GetCommandLineA();
/* 获得环境信息 */
_aenvptr = (char *) __crtGetEnvironmentStringsA();
_setargv(); /* 设置命令行参数 */
_setenvp(); /* 设置环境参数 */
_cinit(); /* C数据初始化:全局变量初始化,就在这里!*/
__initenv = _environ;
mainret = main( __argc, __argv, _environ ); /*调用main函数*/
exit( mainret );
}
从以上代码可知,运行库在调用用户程序的main或WinMain函数之前,进行了一些初始化工作。初始化完成后,接着才调用了我们编写的main或WinMain函数。只有这样,我们的C语言运行时库和应用程序才能正常地工作起来。
除了crt0.c外,C运行时库中还包含wcrt0.c、 wincrt0.c、wwincrt0.c三个文件用来提供初始化函数。wcrt0.c是crt0.c的宽字符集版,wincrt0.c中包含windows应用程序的入口函数,而wwincrt0.c则是wincrt0.c的宽字符集版。
Visual C++的运行时库源代码缺省情况下不被安装。如果您想查看其源代码,则需要重装Visual C++,并在重装在时选中安装运行库源代码选项。
3.各种C运行时库的区别
(1)静态链接的单线程库
静态链接的单线程库只能用于单线程的应用程序,C运行时库的目标代码最终被编译在应用程序的二进制文件中。通过/ML编译选项可以设置Visual C++使用静态链接的单线程库。
(2)静态链接的多线程库
静态链接的多线程库的目标代码也最终被编译在应用程序的二进制文件中,但是它可以在多线程程序中使用。通过/MD编译选项可以设置Visual C++使用静态链接的单线程库。
(3)动态链接的运行时库
动态链接的运行时库将所有的C库函数保存在一个单独的动态链接库MSVCRTxx.DLL中,MSVCRTxx.DLL处理了多线程问题。使用/ML编译选项可以设置Visual C++使用动态链接的运行时库。
/MDd、 /MLd 或 /MTd 选项使用 Debug runtime library(调试版本的运行时刻函数库),与/MD、 /ML 或 /MT分别对应。Debug版本的 Runtime Library 包含了调试信息,并采用了一些保护机制以帮助发现错误,加强了对错误的检测,因此在运行性能方面比不上Release版本。
下面看一个未正确使用C运行时库的控制台程序:
#include <stdio.h>
#include <afx.h>
int main()
{
CFile file;
CString str("I love you");
TRY
{
file.Open("file.dat",CFile::modeWrite | CFile::modeCreate);
}
CATCH( CFileException, e )
{
#ifdef _DEBUG
afxDump << "File could not be opened " << e->m_cause << "\n";
#endif
}
END_CATCH
file.Write(str,str.GetLength());
file.Close();
}
我们在"rebuild all"的时候发生了link错误:
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
main.exe : fatal error LNK1120: 2 unresolved externals
Error executing cl.exe.
发生错误的原因在于Visual C++对控制台程序默认使用单线程的静态链接库,而MFC中的CFile类已暗藏了多线程。我们只需要在Visual C++6.0中依次点选Project->Settings->C/C++菜单和选项,在Project Options里修改编译选项即可。
candy110
2009-09-04
打赏
举报
回复
看编译方面的书吧.
全局变量,static变量,局部变量是放在不同的地方的.
应该是根据这个来给值的.
littlegang
2009-09-04
打赏
举报
回复
数据段
代码段
看看编译原理方面的书
versaariel2009
2009-09-04
打赏
举报
回复
看反汇编。。。
zsyqdr
2009-09-04
打赏
举报
回复
再补充一下:最好说明在系统底层是怎么实现。。。高人快来指点一下
wissup
2009-09-04
打赏
举报
回复
原理:---->请LZ研究计算机语言。《程序语言实践之路》这本书挺好!
实现:----->请研究编译原理。《编译原理》龙书是本好书。
再不行,就研究一下为什么要有计算机语言,这是走原理的上层路线。
下层路线,就直接研究一个编译器源代码。什么?你没有,那我也没有办法了。
还有,如果你懂很底层的汇编语言,应该对这个问题有很大的帮助。
了解了,这个对你应用貌似不大,不过做学问就应该这样,赞一个LZ!
pearling
2009-09-04
打赏
举报
回复
很值得学习,谢谢了!
c语言
全局
变量
和静态
变量
的初始化
因为程序开始运行时要用适当的值来初始化
全局
变量
,所以
初始值
必须保存在编译生成的可执行文件中,因此
初始值
在编译时就要计算出来,然而有些数学函数例如sin(3.14)的值必须在程序运行时调用sin函数才能得到,所以不能用来初始化
全局
变量
。
c语言
中局部
变量
可以用类型相符的任意表达式来初始化,而
全局
变量
只能用常量表达式初始化,尤其对于
全局
变量
来说,不能用一个数学函数或者其他的需要在运行时才能计算出结果的表达式进行初始化。
全局
变量
在定义时如果不初始化则值为0.而局部
变量
如果定义时不初始化值是不确定的。
C语言
中
static
的用法
全局
变量
与局部
变量
C语言
中
static
的用法
全局
变量
与局部
变量
1. 什么是
static
?
static
是
C语言
中很常用的修饰符,它被用来控制
变量
的存储方式和可见性。 1.1
static
的引入 在函数内部定义的
变量
,当程序执行到它的定义处时,编译器为它在栈上分配空间,函数在栈上分配的空间在此函数执行结束时会释放掉,这样就产生了一个问题: 如果想将函数中此
变量
的值保存至下一次调用时,如何实现? 最容易想到的方法是定义为全局的
变量
,但定义一个
全局
变量
有许多缺点,最明显的缺点是破坏了此
变量
的访问范围(使得在此函数中定义
c语言
全局
变量
(
c语言
全局
变量
怎么定义)
菜鸟提问:GCCE编译环境下,汇编函数如何使用C
全局
变量
汇编化了 首先要在C程序中用extern申明该
变量
为
全局
变量
,再在汇编程序中用extern "
变量
名"来导入,注意,汇编中如果直接使用"mov eax,
变量
名"表示的是将该
变量
的地址移入eax,若想取得该
变量
的值请使用[
变量
名]
C语言
全局
变量
的优缺点我们老师...
C语言
中
static
全局
变量
与普通的
全局
变量
区别
下面是中兴通讯2012校招笔试题的一道问答题: 1.
static
全局
变量
与普通的
全局
变量
有什么区别 ?
全局
变量
(外部
变量
)的说明之前再冠以
static
就构成了静态的
全局
变量
。
全局
变量
本身就是静态存储方式, 静态
全局
变量
当然也是静态存储方式。 这两者在存储方式上并无不同。 这两者的区别在于非静态
全局
变量
的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变...
c 语言
全局
变量
初始化,C中
全局
变量
和
static
变量
的存储与初始化
目标文件、可执行程序及其他二进制文件以ELF格式存储在磁盘中,该文件有两个重要的段(section),即代码段和数据段。数据段又分为:.data 段 和 .bss段,其中.data段存储已初始化的
全局
变量
和静态
变量
,.bss 段存储未初始化的
全局
变量
。在C中,凡是在任何代码块之外声明的
变量
总是存储于静态内存中,也就是不属于堆栈的内存,这类
变量
称为静态(
static
)
变量
。——C和指针(p43)这句...
C语言
70,011
社区成员
243,256
社区内容
发帖
与我相关
我的任务
C语言
C语言相关问题讨论
复制链接
扫一扫
分享
社区描述
C语言相关问题讨论
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章