C语言变量那些事(堆栈、数据段、代码段、作用域、生命周期)

2023-06-10 09:37:14 浏览数 (1)

学习C语言变量内容,看似对编程无关紧要,但总有那些人想要知其然,知其所以然,于是乎本文介绍关于变量的存储类型,作用范围及生命周期。为后续编程可能出现的结果错误,提供一些指导与经验。

1. C语言是强类型语言

什么是强类型语言

强类型语言需要事先确定变量的类型,是int型、float型、还是char型等。当前诸如python、shell、Matlab等变量为弱类型。

实现过程:

对于弱类型变量其实是编译器帮你封装好了(C语言也可以通过结构体实现不同类型变换)

代码语言:javascript复制
	struct student 
	{
	int age
	};
	
	int main()
	{
	typedef student A;
	AA.num = 5;
	AA.age = 6;
	return 0;
	}

其中变量AA就有两种类型:float 和 int。

2. C语言变量与内存

经常听说堆栈,其实这个词要分开说:堆,栈。数据段、代码段、bss段又是什么呢?

2.1 堆需要申请

代码语言:javascript复制
malloc xxxx;    //申请
bzero;            //释放(防止内存是脏的)

案例(链表):

代码语言:javascript复制
	struct node
{
	int a;
	struct node* pNext;
};
int main(void)
{
	struct node* p1 = (struct node*)malloc(sizeof(struct node));
	
	// 判断内存空间是否申请到
	if (NULL == p1)
	{
		printf("malloc erro");
	}
	
	// 清理申请到的内存,防止内存是脏的
	bzero(p1,sizeof(struct node));
	
	// 向节点数据进行赋值
	p1->a = 1;
	p1->pNext = NULL;
}

因此,相关变量存放在堆中需要进行申请。所以可以推倒得知相关变量的生命周期为:申请到释放过程。(注意:后续全局变量是存放在数据段中,而数据段是另一种存储方式)

2.2 栈存放大多数局部变量

局部变量包含:自定义函数内,main函数内定义的变量。

(一般情况是:栈的内存比较小,当程序定义太多的局部变量时会导致栈满溢出的情况。对于其它弱类型语言,相关编译器已经对变量进行了改装,自己无需考虑是否会栈满的情况。)

为什么说栈存放大多数局部变量?

原因:C语言中有 static关键字。其可以将局部变量存储在栈上改变为存储在数据段或bss段

(弱类型语言中的编译器其实也是帮你分配好了相关数据的存储类型,只不过C语言需要自己设定)

2.3 数据段存放全局变量和非0的静态局部变量

全局变量简单来说:不在自定义函数内,不在main函数内定义的变量为全局变量。(大多数时候全局变量的位置在#include<xx>的后面)

在编程中,全局变量可以在任何函数中进行调用,也可以在不同文件中进行调用(但需要在调用文件中进行声明:extern int b;)

全局变量在文件中的作用也暗示了其生命周期为程序的一生,由于生命周期很长故其存放的位置也必须要有足够的容量一直被全局变量所占用,故全局变量存储在数据段上。(同时作为局部变量的b来说,static int b = 4;,由于b是非0的静态局部变量其也存放在数据段上)

2.4 代码段和bss段

代码段存放函数(对于非函数部分,诸如#include<xx>,宏定义,全局变量等在.c文件编译过程中进行的处理与替换)

bss段存放变量剩下的:显示或未显示初始化为0的数据段

3. 变量的作用域

3.1 局部变量

根据局部变量存储在栈上,其生命周期段,那么作用范围一定是非常有限的。一般就在{}之间

案例:

代码语言:javascript复制
#include<stdio.h>

int main(void)
{
	int b =1;
	while(1)
	{
		int b = 2;
		printf("b = %d.n",b);
		break;
	}
	printf("b = %d.n",b);
	return 0;
}

// 结果是:
b = 2.
b = 1.

3.2 全局变量

根据全局变量储存在数据段上,生命周期为程序一生,故其作用域范围很广:整个文件和其他文件也可以调用(调用需要声明 extern int b;)

0 人点赞