首页 > C > 数据类型与变量 阅读:57,774

变量类型,作用域,存储空间与生命周期

变量的作用域:指变量能够在什么地方被访问。比如有的变量只能在函数内部访问,有的变量是所有函数都能访问。

变量的存储空间:存放变量的内存位置。要明白变量在内存中存放的位置,首先就先了解下系统的内存布局。

x86为例,x86支持32位寻址,因此可以支持最大232=4GB的虚拟内存空间(也可以通过PAE技术增加到36位寻址,因此可以将寻址空间扩大到64GB)。如图所示,在4G的虚拟地址空间中,Windows系统的内存主要分为内核空间和应用层空间上下两部分,每部分各占约2GB,其中还包括了一个64KBNULL空间以及非法区域。Windows内存的逻辑地址包含2部分,即段选择符和偏移地址,CPU在做地址翻译的时候,通过分段机制计算出一个线性地址,再通过页表机制映射到物理地址以便存取物理内存中的数据和指令。

X64AMD64)的内存布局与X86的内存布局类似,不同的地方在于各自空间的范围和大小不同,同时X64下还存在着一些空洞(hole),如图所示。在X64内存理论上支持最大264的寻址空间,但实际上这个空间太大了,目前根本用不完,因此实际上的X64系统一般都只支持到40多位(比如Windows支持44位最大寻址空间为16TBLinux 支持48位最大寻址空间256TB等),支持的空间达到了TB级别。但是,无论是在内核空间还是在应用层空间,这些上TB的空间并不都是可用的,存在着所谓的空洞。

 

 

当程序加载入内存后,程序在内存中可以分为若干个区,这些区包括:静态区(.data,.rdata,.bss段等),代码区(.text),堆区,栈区等。

.text 代码段,这个存放代码的,用汇编角度来看就是指令。

.rdata 只读数据段,存放常量,字符常量,const常量。

.data 数据段,存放已经初始化好的全局变量和静态变量。

.bss 存放未初始化的全局变量和静态变量。

.rdata.data.bss都是存放的数据。除了.bss段,.rdata.data段的值都是在编译的时候就确定了,并且将其编译进了可执行文件,经过反汇编都能找得到。bss段是在代码运行的时候手动编写汇编代码将其初始化为0的(这就是未初始化的全局和静态变量默认值为0的根源)

.stack:栈区,存放局部变量等。如下图所示,栈区存放这函数调用过程中的形参,返回地址以及局部变量等(将在函数一章讲调用约定的时候具体介绍栈上的数据)。

变量的生命周期:变量有效的时间段,只有在变量的生命周期内,才能访问该变量。有的变量的生命周期是函数运行期间,函数结束,变量就消失了。有的变量的生命周期是程序运行期间,只要程序还未结束,变量就不会消失或销毁。

变量分类:全局变量,局部变量,静态变量(静态全局变量和静态局部变量),寄存器变量,外部变量。

全局变量:全局变量的说明的位置在所有函数之外 ,整个程序可见,生命周期为整个程序运行期间,存储位置为静态存储区。

局部变量:在函数内部说明的变量为局部变量,只有在函数执行时,局部变量才存在,当函数执行完退出后,局部变量随之消失。作用域为函数内部,存储空间为栈。

全局静态变量:与全局变量唯一不同的地方是别的文件不能访问该变量

局部静态变量:与局部变量的区别是,存储在静态区,整个程序运行期间有效,具有记忆功能,只初始化一次,默认初始化为零

寄存器变量:不像其他变量那样在内存中存放数据,而是在CPU的寄存器中暂存数据,使用寄存器变量比使用内存变量的操作速度快得多。只有整型和字符型变量可定义为寄存器变量。由于CPU中寄存器有限,尽量减少使用数量和和占用时间,用完马上释放;不能定义为全局变量,也不能定义在结构或者类中。

extern关键字:为了解决全局变量和函数的共用问题,就引入了 extern关键字。这样只需在一个文件中定义全局变量和函数,在另一个文件中要用到这些变量和函数时,只需将那个文件中的变量和函数说明表复制过来,在前面加上extern,告诉编译器,这些变量和函数已经在别的文件中定义说明。

 

//main.cpp

int a = 0; //全局变量

char *p1; //全局变量

static int x=10; //全局静态变量,10为常量

void func(void)

{

       int b; //局部变量

       char s[] = “123”; //s为局部变量,123”为常量

       char *p2; //p2为局部变量

       char *p3 = “hello, world”; //p3为局部变量,”hello, world”为常量

       static int c =0;//局部静态变量

       register int i =0;//寄存器变量        

       p1 = (char *)malloc(128); //p1指向堆上的内存,直到free

       p2 = (char *)malloc(256);//p2指向对上的内存,直到free

       free(p1);

       free(p2);

}

int main(void)

{

    func();

    printf(hello world\n);

    return 0;

}

 

归纳起来,不同类型变量的存储空间,作用域与生命周期如下表所示:

变量类型

存储空间

作用域

声明周期

全局变量

静态区(.data存放初始化全局变量,.bss存放未初始化全局变量)

整个程序

程序运行期间

全局静态变量

静态区(.data存放初始化全局变量,.bss存放未初始化全局变量)

当前源文件

程序运行期间

局部变量

当前函数内部

函数执行期间

局部静态变量

静态区

当前函数内部,只初始化一次

程序运行期间

寄存器变量

寄存器

当前函数

函数运行期间

周哥教IT,分享编程知识,提高编程技能,程序员的充电站。跟着周哥一起学习,每天都有进步。

通俗易懂,深入浅出,一篇文章只讲一个知识点。

当你决定关注「周哥教IT」,你已然超越了90%的程序员!

IT黄埔-周哥教IT技术交流QQ群:213774841,期待您的加入!

二维码
微信扫描二维码关注