C中全局变量和static变量的存储与初始化

2018-08-08  本文已影响0人  丹丘生___

目标文件、可执行程序及其他二进制文件以ELF格式存储在磁盘中,该文件有两个重要的段(section),即代码段和数据段。
数据段又分为:.data 段 和 .bss段,其中.data段存储已初始化的全局变量和静态变量,.bss 段存储未初始化的全局变量。

在C中,凡是在任何代码块之外声明的变量总是存储于静态内存中,也就是不属于堆栈的内存,这类变量称为静态(static)变量。——C和指针(p43)

这句话中有两个概念需要搞清楚:


这时,我们也许想问,运行前是如何创建静态变量的?

我们知道,编译-汇编后生成二进制目标文件(ELF格式),虽然还不是最终的可执行文件,但已经有了代码段和数据段,而此时数据段中的.data段中已经有了‘已初始化的静态变量’的磁盘存储空间,并被填充了初始化值,在进程加载时直接被映射至内存空间中。

而.bss段实际上未占据任何磁盘存储空间,也就是徒有其名,无有其实,只是在ELF的section header table 中记录其应该分配到的磁盘存储空间,而直到可执行程序被加载到内存中时,加载器将依据.bss段的section header中的信息,在内存中为其分配空间。

总结来说就是,运行前创建分为两种:编译时创建——>加载时映射至内存;加载时创建。


此时,我们仍有疑惑,静态变量的创建肯定是在运行前了,那么未初始化变量的初始化到底是在什么时候进行的?

有三个猜测:

(C和指针)在静态变量的初始化中,我们可以把可执行文件想要初始化的值放在当程序执行时变量将会使用的位置(注:实际上就是磁盘文件.data 段),当可执行文件载入到内存时,这个已经保存了正确初始值的位置将赋值给那个变量……如果不显式地指定其初始值,静态变量将初始化为0。

这段话说的比较晦涩,因为它不想引入过多程序装载过程的知识。但我们也可以借此判断,未初始化的全局变量实际上和static一样会被初始化为0,只不过它是在可执行文件载入到内存时发生的。

//in C
int x = 5;
static y = x; //error

//in C++
int x = 5;
static y = x; //correct

最终总结:
在C中,静态变量,即全局变量和static变量,是在程序运行前创建的,其中已初始化的全局变量和static变量在编译汇编成目标文件时,初始值就已经保存在磁盘的.data段了,进程加载时将其映射到内存空间即可;
未初始化的全局变量需要进程加载时真正的为.bss段分配内存空间,并赋值为0。静态变量的创建和初始化都是在运行前完成的,切记C中不能动态初始化,这一点与C++不同。

上一篇 下一篇

猜你喜欢

热点阅读