38、程序中的三国天下

1、程序中的栈

  • 栈是现代计算机程序里最为重要的概念之一(这个栈和数据结构里面的栈概念上一样,表现形式上不一样)
  • 栈在程序中用于维护函数调用上下文
  • 函数中的参数和局部变量存储在栈上
    在这里插入图片描述

注:
1、栈:就是一种后进先出的行为
2、在这里要注意由于在intel系统中栈是向下生长的(栈越扩大其值越小,堆恰好相反)

  • 栈保存了一个函数调用所需的维护信息
    在这里插入图片描述
    esp:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。函数调用结束之后的返回地址
    ebp:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。

  • 函数调用时,对应的栈空间在函数返回前是专用的

  • 函数调用结束后,栈空间被释放,数据不再有效,当你再次进行函数调用时就会出错,因为空间被别人用了。如果没进行函数调用,用一下历史数据也是可以的。

#include <stdio.h>
#include <malloc.h>
int* g()
{
	int a[10] = { 0 };
	return a;
}
void f()
{
	int i = 0;
	int b[10] = { 0,1,2,3,4,5,6,7,8,9 };
	int* pointer = g();
	for (i = 0; i < 10; i++)
	{
		b[i] = pointer[i];
	}
	for (i = 0; i < 10; i++)
	{
		//printf("%d\n", b[i]);
		printf("%d\n", pointer[i]);
	}
}
int main()
{
	f();

	return 0;
}

在这里插入图片描述
在这里插入图片描述
第二个程序里面 pointer指向的内存已经被释放了,变成了野指针。
但是我觉得还有原因在于你想返回局部变量的地址。如果没进行函数调用,用一下历史数据也是可以的,就像第一个程序,把值赋给了别人,期间没有发生函数调用,于是虽然有野指针,但是数据也是对的。但是第二个程序错误在于运行 printf 函数相当于进行了函数调用,此时内存里面的数据被销毁了。

2、程序中的堆(malloc)

  • 堆是程序中一块预留的内存空间,可由程序自由使用
  • 堆中被程序申请使用的内存在被主动释放前将一直有效
    为什么有了栈还需要堆?
      栈的作用是为了函数调用,往往在程序运行的时候需要临时的内存空间,因为栈上的数据在函数返回后就会被释放掉,无法传递到函数外部,所以就需要堆空间
  • C语言程序中通过库函数的调用获得堆空间
    — 头文件:malloc.h
    — malloc:以字节的方式动态申请内存
    — free:将堆空间归还给系统
  • 系统对堆空间的管理方法
    — 空闲链表法,位图法,对象池法等等
    在这里插入图片描述
    其主要意思就是系统会给你的内存不是你想要的,而是上面接近你的。

3、程序中的静态存储区

  • 静态存储区随着程序的运行而分配空间
  • 静态存储区的生命周期直到程序运行结束
  • 在程序的编译期静态存储区的大小就已经确定
  • 静态存储区主要用于保存全局变量和静态局部变量
  • 静态存储区的信息最终会保存到可执行程序中
#include <stdio.h>

int g_v = 1;			//全局变量
static int g_vs = 2;    //static修饰的全局变量,不能被外部文件访问
void f()
{
	static int g_vl = 3;			//static修饰的局部变量,具有全局生命周期
	printf("%p\n", &g_vl);
}
int main()
{
	printf("%p\n", &g_v);
	printf("%p\n", &g_vs);
	f();
	return 0;
}

在这里插入图片描述
结论:从得出的结果我们可以看出,全局变量,static修饰的全局变量和static修饰的局部变量都存储在同一个地方,也就是程序的静态存储区,内存地址都是相邻的。

4、小结

  • 栈,堆和静态存储区是程序中的三个基本数据区
    栈区主要用于函数的使用
    — 堆区主要是用于内存的动态申请和归还
    — 静态存储区用于保存全局变量和静态变量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值