C语言内存分区,变量的作用域和生存周期

C语言内存分区


   内存分为栈区(stack),堆区(heap),全局区(静态区)(data区),代码区(text segment)四个区。而每一个内存分区,又起着不同的作用。

  • 栈区(stack):栈是一种先进后出的内存结构,由编译器自动分配释放,存放函数的参数值、返回值、局部变量等。在程序运行过程中实时加载和释放,因此,局部变量的生存周期为申请到释放该段栈空间。

  • 堆区(heap):堆是一个大容器,它的容量要远远大于栈,但没有栈那样先进后出的顺序。用于动态内存分配。一般由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。

    栈区的生长方向是向下生长,堆区是向上增长。

  • 全局区(静态区)(data区):在这个分区里面存放着3个东西:

    • 未初始化的数据(BBS区):全局未初始化数据,静态未初始化数据

    • 初始化的数据区:全局初始化数据,静态初始化数据,全局区默认初始化为0

    • 文字常量区:字符串常量

      全局区存放的是:
      全局变量,静态变量,文字常量。

  • 代码区(text segment):加载的是可执行文件代码段,所有的可执行代码都加载到代码区,这块内存是不可以在运行期间修改的。
    C语言内存分区,变量的作用域和生存周期_第1张图片

变量的作用域和生命周期:

作用域:就是变量的范围
生命周期:就是变量的有效期

  • 普通局部变量
    • 1、在{}内部定义的变量就是局部变量。
    • 2、只有执行到定义变量的这个语句,系统才会给整个变量分配空间。
    • 3、当离开{}这个非静态局部变量自动释放,无法使用。
    • 4、局部变量的作用域在当前{},离开此大括号,变量无法使用。
    • 5、普通局部局部变量也叫自动变量auto。
    • 6、不在同一作用域的变量可以同名。取的时候是就近原则。
    • 7、普通局部变量不初始化默认为随机数。
 #include
int main()
{
int a=101;
if(1)
{

	int a = 2;
	printf("我是for循环里是a:%d\n", a);
}
printf("我是外面的a:%d\n", a);
return 0;
  • 静态局部变量
    • 1、在{}内部定义的变量就是局部变量。
    • 2、函数没有调用前就存在。
    • 3、当离开{}这个静态局部变量不会自动释放,只有程序程序结束,static变量才自动释放。
    • 4、局部变量的作用域在当前{},离开此大括号,变量无法使用。
    • 5、不在同一作用域的变量可以同名。取的时候是就近原则。
    • 6、如果局部变量不初始化,默认为0
    • 7、值有执行到的时候才初始化,初始化语句只会执行一次,但可以赋值多次。
    • 8、静态变量只能用常量初始化。
void static_fun()
{
	static int i = 1;
	i++;
	printf("%d\n",i);
}
int main()
{
	static_fun();
	static_fun();
} 	

普通局部变量和静态局部变量区别:

  1. 内存分配和释放

    • 普通局部变量只有执行到定义变量的语句才分配空间。
    • 静态局部变量在编译阶段(函数还没有执行),变量的空间已经分配。
    • 普通局部变量离开作用域{},自动释放。
    • 静态局部变量只有在整个程序结束才自动释放。
  2. 初始化

    • 普通局部变量不初始化,值为随机数。
    • 静态局部变量不初始化,值为0。
    • 静态局部变量初始化语句只有第一次执行时有效。
    • 静态局部变量只能用常量初始化。
  • 普通全局变量
  1. 在{}外面(函数外面)定义的变量为全局变量。
  2. 只有定义了全局变量,任何地方都能使用此变量。
  3. 如果使用变量时,在前面找不到此全局变量的定义,需要声明才能使用。
  4. 全局变量不初始化,默认赋值为0。
  5. 声明只针对全局变量,不针对声明多次。
  6. 全局变量在编译阶段已经分配空间,程序结束,自动释放。
  7. 全局变量只能定义一次,可以声明多次。
  8. 不同文件,普通全局变量只能定义一次,可以声明多次。
void static_fun()
{
	extern int i;//声明全局变量
	i++;
	printf("%d\n",i);
}
int i = 1; //全局变量定义在下面
int main()
{
	static_fun();
	static_fun();
}

C语言对全局变量的缺陷:
如果定义一个全局变量,没有赋值(初始化),无法确定是定义,还是声明。
如果定义一个全局变量同时初始化,这个肯定是定义。
如果声明一个全局变量,建议初始化,如果声明一个全局变量建议加extern关键字

分文件编程的时候定义只定义在.c里定义,头文件用来声明来防止重复定义。

  • 静态全局变量

    1. 静态全局变量和普通全局变量的区别就是作用域不一样。
    2. extern关键字只适合普通全局变量
    3. 普通全局变量所有文件都能使用,别的文件不能使用。
    4. 静态全局变量只能在本文件中使用,别的文件不能使用。
    5. 不同的文件只能出现一个普通全局变量的定义。
    6. 一个文件只能有一个静态全局变量的定义,不同文件之间的static全局变量,就算名字相同,也是没有关系的两个变量。
    • 普通函数和静态函数(文件作用域不一样)
    1. 所有的文件只能有一次普通函数的定义。
    2. 一个文件可以有一个静态函数的定义
    3. 普通函数所有文件都能调用,前提是声明
    4. 静态函数只能在定义所在的文件中使用

你可能感兴趣的:(C)