目录
一、作用域
作用域是变量可以被访问的区间,变量的作用域可以分为以下四种:
1.进程作用域(全局):
在当前进程的任何一个位置都可以访问;
2.函数作用域:
当流程转移到函数后,在其开始和结束的花括号内可访问;
3.块作用域:
块是用花括号“{}”括起来的代码区域,定义在块中的变量具有块作用域。块作用域的可见范围是从定义处到包含该定义的块的末尾;
4.文件作用域:
在当前源码文件内可以被访问。
注:
局部变量的作用域为当前函数的“{}”之间,全局变量的作用域为当前的整个源文件或者工程。
二、生命周期
生命周期就是从创建该变量开始到该变量被销毁的时间。
各变量的生命周期:
1.全局变量:
进程开始时创建,进程结束时销毁,在代码编译链接后,直接将其初始值写入到可执行文件中,创建时按照定义时的初始值进行赋值;
2.局部变量和参数变量:
进入函数时创建,退出函数时销毁;
3.静态变量(静态局部变量和静态全局变量)static
(1)静态局部变量:
在函数内使用static修饰一个变量,它的生命周期将同全局变量一样,作用域被限制在函数内。
特点是是其拥有记忆能力,不会在每次声明的时候都初始化一次,这个作用在用来实现计数功能的时候非常方便,例如:
void cnt(void)
{
static int num = 0;
num++;
}
函数中,变量num是静态局部变量,在第一次进入函数的时候被声明,然后执行自加操作,当第二次进入函数时,num不会被重新初始化变成0,而是保持1,再自增,其作用域仍然是cnt函数体内。
(2)静态全局变量:
生命周期和全局变量一样,但是作用域被限制在定义文件内,无法使用extern来让其他源文件中使用它。
静态全局变量的优势是增强了程序的安全性和健壮性,同时提高可移植性。如果对于一个变量而言,假设不期望其它文件有修改这个变量的能力,但其它文件又需要该变量的值,就可以在源文件中定义一个静态全局变量,同时使用函数对其的值进行修改和获取,对外只提供函数接口即可,其它文件通过函数接口间接使用该变量。
注:
(1) 静态全局变量只在本文件可见,因而其它文件也可以定义相同名字的静态局部变量。但不利于程序的可读性和可维护性,容易让开发变得混乱。
(2) static关键字除了用来修饰变量之外,还可以用来修饰函数,让函数仅在本文件可见,其它文件无法对其进行调用。
生命周期由变量在内存中的位置决定。存储位置不同,作用不同,生命周期不同。
注:变量同名问题
1.不同函数中的局部变量可以同名,互不影响;全局变量不能同名;
2. 当局部变量和全局变量同名时,局部变量将覆盖全局变量。
三、作用域与生命周期的关系
二者其实并无本质上的联系
1.作用域是语法层面对变量是否可见的规定,可以理解为空间维度;
2.生命周期是二进制层面变量存在于内存中的时间,可以理解为时间维度。
四、内存分配
在C语言中内存分别分为栈区(stack)、堆区(heap)、未初始化全局数据区、已初始化全局数据区、静态常量区(static)、代码区(data)。
1.栈(stack):
存放函数形参和局部变量,函数结束返回时自动释放空间。先进后出,向地址减小方向增长(由高地址到低地址)。
栈的特点:
(1)运行时自动分配和自动回收:栈是自动管理的,程序员不需要手工干预。方便简单。
(2)反复使用性:栈内存在程序中其实就是那一块空间,程序反复使用这一块空间。
(3)遗留性:栈内存由于反复使用,每次使用后程序不会去清理,因此在使用栈时还是上次栈中遗留下的数值。
(4)临时性:函数不能返回栈变量的指针,因为这个空间是临时的。
(5)溢出性:因为操作系统事先给定了栈的大小,如果在函数中无穷尽的分配栈内存总能用完。
2.堆(heap):
c语言中使用malloc、realloc、calloc等开辟的内存就在堆,从向地址增大方向增长(低地址向高地址)。由程序员手动分配释放的储存区,如果程序员不手动释放这块内存,内存将一直被占用,直到程序运行结束由系统自动收回。
3.全局区:
全局变量、静态变量 (static)(全局和局部静态变量),以及字符串常量(不能随意修改)(const修饰的全局变量也储存在常量区,const修饰的局部变量依然在栈上)。
数据段(data段)、bss段
(1).data段(rw段)存:被初始化为非0的全局变量、被初始化为非0的static局部变量
(2).bss段(又叫ZI段(zero initial))存:未被初始化或初始化为0的全局变量;未被初始化的static修饰的局部变量。
4.常量区:
编译时,以地址的形式编码于指令代码中。比如字符串常量、const修饰的全局变量。
代码段、rodata段(只读数据段)
(1)对应程序中的代码(函数),代码段又叫文本段(.text)
(2)rodata段用常常用于存储常量数据,rodata又被称为只读段,只读数据段在程序运行期间只能读不能写,比如const修饰的常量有可能就存储在rodata段。

几张助理解的示例图:



本文详细介绍了C语言中变量的作用域,包括全局、函数、块和文件作用域,以及变量的生命周期,如全局变量、局部变量和静态变量。此外,还阐述了作用域与生命周期的关系,并探讨了内存分配,包括栈区、堆区、全局区和常量区的特点和管理方式。
2074






