程序中的栈
栈是现代计算机程序里最为重要的概念之一
栈在程序中用于维护函数调用上下文
函数中的参数和局部变量存储在栈上
栈是一种行为,后进先出。
栈保存了一个函数调用所需的维护信息。
例如:参数、返回地址、局部变量、调用上下文、寄存器信息、其他数据信息
函数调用过程
每次函数调用都对应着一个栈上的活动记录
调用函数的活动记录位于栈的顶部
被调用的活动记录位于栈的顶部
函数调用的栈变化一
从main()调用f()
栈底 | main()参数 |
---|---|
返回地址 | |
ebp→ | old ebp |
数据信息 | |
f()参数 | |
返回地址 | |
old ebp | |
esp→ | 数据信息 |
函数调用栈上的数据
函数调用时,对应的栈空间在函数返回前是专用的
函数调用结束后,栈空间将被释放,数据不再有效
千万不要返回局部变量的地址
在栈空间中,局部变量的地址会被销毁的,局部变量的地址是没有意义的。
例子39-1:
#include "stdio.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]);
}
}
int main()
{
f();
return 0;
}
输出结果:
0
0
0
0
0
0
0
0
0
0
pointer所指的g()的返回值赋值给b,打印出结果
例子39-1修改:
#include "stdio.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]);
}
}
int main()
{
f();
return 0;
}
输出结果:
0
1
2
3
4
5
6
7
8
9
输出结果改变了,验证了局部变量的地址是不可靠的。
程序中的堆
堆是程序中一块预留的内存空间,可由程序自由使用
堆中被程序申请使用的内存在被主动释放前将一直有效
如果一直申请堆空间,不释放,将会导致堆空间被申请完了,程序运行会越来越慢,最后导致无法运行。
为什么有了栈还需要堆?
栈上的数据在函数返回后就会被释放掉,无法传递到函数外部,如:局部数组
程序中的堆
C语言程序中通过库函数的调用获得堆空间
头文件:malloc.h
malloc 以字节的方式动态申请堆空间
free 将堆空间归还给系统
系统对堆空间的管理方式
1.空闲链表法 2.位图法 3.对象池法等等
int p = (int)malloc(sizeof(int)); //申请4字节
程序中的静态存储区
静态存储区随着程序的运行而分配空间
静态存储区的生命周期直到程序运行结束
在程序中编译期静态存储区的大小就已经确定
静态存储区主要用于保存全局变量和静态局部变量
静态存储区的信息最终会保存到可执行程序中
例子39-2:
#include "stdio.h"
int g_v = 1;
static int g_vs = 2;
void f()
{
static int g_vl = 3;
printf("%p\n",&g_vl);
}
int main()
{
printf("%p\n",&g_v);
printf("%p\n",&g_vs);
f();
return 0;
}
输出结果:
007E7000
007E7004
007E7008
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。