堆和栈
堆
堆即为一块空闲的内存,从这块内存中来取出一部分用完之后再把它释放回去
//此时heap_buf就相当于一块空闲的内存
//我们只需要在它上面实现内存的分配和释放,那么它就是一个堆
char heap_buf[1024];
int pos = 0; //指针(指向空闲内存的位置)
//分配空间
void * my_malloc(int size)
{
int old_pos = pos; //旧的下标
pos += size; //下标更新
return &heap_buf[old_pos]; //分配空间(返回首地址)
}
//释放分配出去的某一块内存(因为此时是没法释放的,所以就没写代码,意识一下即可)
void my_free(void * size)
{
/* err */
}
int main(void)
{
int i;
char * buf = my_malloc(100); //分配100个字节的空间
unsigned char uch = 200;
for(i=0;i<26;i++)
{
buf[i] = 'A' + i;
}
}
此时heap_buf就有数据了,并且下一次分配空间的时候,是从地址100开始分配的,因为pos指向100
栈
栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
void c_fun(void)
{
;
}
void b_fun(void)
{
;
}
int a_fun(int val)
{
int a = 8;
a += val;
b_fun();
c_fun();
return a;
}
int main(void)
{
a_fun(40);
return 0;
}
基本知识:
- 返回地址:可以理解为返回地址就是该函数执行结束后的下一条指令
在main函数中,a函数执行完之后将会返回到return 0中
a函数中调用函数b,当b函数执行之后将会返回到c函数调用前,c函数执行完之后返回到return a中
在c语言中,上面过程我们一目了然就知道了它返回的地址是谁,但这个返回地址保存在哪里呢?
1、返回地址保存在哪?
- 返回地址保存在栈中
- main在调用a_fun前会做两两件事情:
- 将a的返回地址(return 0的地址)保存到一个寄存器里面LR(link Register)
- 调用a_fun
- 那么a_fun里面调用b_fun之前,就要先把b_fun的返回地址(c_fun)保存到LR里面,之后在调用b_fun
2.那么在a_fun里面保存的LR会不会覆盖之前LR的数据呢?如果不会,LR里面是如何处理的?
- LR并不会被覆盖
- 在a_fun内部会做一件事情:
- 把LR的值(main里面的return 0的地址)存入栈中
- 同样道理,b_fun的内部也会将LR的值(c_fun的地址)存入栈中,b_fun执行完就会开始执行c_fun
- 当c_fun执行完,就会取出c_fun保存的LR值,并跳过去执行(return a),a函数也一样,最终跳到main函数的return 0
C函数开头:
- 划分栈(LR等寄存器、局部变量)
- 将LR等寄存器存入栈
- 执行代码
- 如代码里面有a = 8的话,会先把a在栈里面划分空间,之后再把8这个值写到栈中