C语言-浅谈程序内存空间的分区及变量与函数的堆栈空间分配,变量初始化未赋值情况

.cpp/.c (原文件)
经过预编译 但是代码中以#开头的代码,都是在预编译完成的,而且不进行类型检查,只进行替换
.i
经过编译 进行类型和语法的检查
.o/.obj
经过链接
.exe

程序运行时分为4个区块来存放数据
分别为
.text 代码区
.data 数据区
.heap 堆区
.stack 栈区
进程:程序运行一次

进程分为以下
就绪态:获取运行的资源
运行态:可以出到别的状态,但是只能从就绪态进入
阻塞态:如进入I/O输入时
睡眠态:该状态在睡眠时间结束后可以自动恢复正常
挂起:挂起后需要给状态才能恢复正常状态
之所以讲做栈空间,是因为它的是使用形式和数据结构栈的特点一样,都是先进后出
我们在程序中使用的变量,函数都是需要内存空间的,这个时候栈区空间,为这些函数和变量,分配栈帧来给他们使用。

全局变量在数据区局部变量在栈区,常量在数据区,还有静态变量也在数据区
malloc开辟的动态空间在堆区。

栈帧再给函数分配空间空,当函数使用完毕时,会回收释放空间。
不管以什么形式调用函数,都会给该函数分配栈帧空间

int a = 0; a全局初始化,数据区
char p1; p1全局未初始化 数据区
main()
{
int b;char s[] = "abc";char p2;char p3 = "123456"; 123456/0在数据区,p3在栈上。
static int c =0; 全局(静态)数据区
p1 = (char )malloc(10);
p2 = (char *)malloc(20);
分配得来得1020字节的区域就在堆区。
strcpy(p1, "123456"); 123456/0放在数据区,编译器可能会将它与p3所指向的"123456"
优化成一个地方。
}

但是有一个例外,但我们把变量设置为静态变量static时,他存放于数据区

下面则个例子将对栈帧空间的分配和调用做解释

void fun(int a)
{
	a += 10;
}
int add(int a, int b)
{
	int c = a + b;
	return c;
}
void main()
{
	int x = 10;
	int y = 20;
	int z = 0;
	fun(x);
	z = add(x, y);
}

上面的函数首先程序从main函数执行,那么栈空间为main函数分配一个栈帧空间,在这个栈帧中分别用做x,y,z的内存空间。当程序执行到fun()函数时,栈为fun函数分配另一个栈帧,在这个栈帧中,为它的形参a开辟了一个空间,然后从主函数中将x传值给a,然后进行a+=10运算,这是形参a的值变为了20.但是主函数的栈帧空间中x的值是不会改变的,因为形参的变化不会改变实参的值。
当fun()函数执行完毕后,系统会将fun()所占有的栈帧给释放这是主函数要执行到z=add()函数了,那么就会将原来给fun()函数的栈帧,重新分配给add()函数。这就像酒店一样,当一楼作为大厅时,有一个客人来了,那么酒店就会把二楼作为新空间分配给第一个客人,当第二天客人走后,第二个客人来了,酒店不可能把三楼的房子给客人,而把二楼空出来不用,那么空间不就浪费了吗,所以他会把二楼的房子打扫干净后再次给第二个客人使用。
那么同样在给add()函数内的变量分配空间后,将执行return c;这条语句,这个语句有两个过程,首先它会在内存中开辟一个临时空间,作为保存c的值,然后将临时空间的值返回赋值给主函数中的z变量
这是add()函数就执行完毕了,那么同样系统就会把add函数占用的栈帧空间给释放回收。最后当main函数执行完毕后同样会回收main函数的栈帧空间。

下面我来分布图解
在这里插入图片描述
当fun函数执行完后
在这里插入图片描述
最后执行return函数时
在这里插入图片描述
最后add函数执行完毕,将这个栈帧释放,这个操作和第二步中的fun函数空间释放相同

这里就设计程序生存期问题可以看我的另一个博客,里面有一些其他解答
生存期描述

c语言中函数对形参的读取是从右到左的

关于全局变量和局部变量初始化未赋值情况

全局变量未初始化是0值
局部变量未初始化是随机值

int a=10;//数据
int ar[10];//数组的值都为0;在数据区中存在BSS段(Block Started by Symbol)通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。特点是:可读写的,在程序执行之前BSS段会自动清0。所以,未初始的全局变量在程序执行之前已经成0了。
会将其填充为0;

struct student
{
int id;
int age;
}

student s1;

const int max;//以及无法编译通过,但是常变量都需要初始化才能使用
int main()
{
int x=10;//代码
printf("%d,%d",s1. id,s1.age);//输出的结结果都为0;
printf(" ",s1)//这样的写法是错误的,因为prinf函数没有输出整个结构体的格式操作符(%?)

const int min;
//无法编译通过,min为初始化,那么min的值为随机值,然后将其设置为const只读属性  //那么min这个变量就没有意义;

}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值