堆和栈

堆即为一块空闲的内存,从这块内存中来取出一部分用完之后再把它释放回去

//此时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;
	}
}

cubemx freertos 栈大小_单片机

此时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前会做两两件事情:
  1. 将a的返回地址(return 0的地址)保存到一个寄存器里面LR(link Register)
  2. 调用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函数开头:

  1. 划分栈(LR等寄存器、局部变量)
  2. 将LR等寄存器存入栈
  3. 执行代码
  • 如代码里面有a = 8的话,会先把a在栈里面划分空间,之后再把8这个值写到栈中