C语言初阶——栈帧和两个经典递归

目录

一.栈帧

1.概念

         (1) 栈

 (2)压栈push

 (3)出栈pop

2.了解寄存器

(1)入栈

(2)出栈

3.了解汇编指令

4.main函数的调用

5.main函数栈帧的创建

(1)main汇编语言

(2)图解

 6.变量的栈帧创建

(1)变量的汇编语言

(2)图解 

 7.函数传参

(1)传参的汇编语言

(2)图解

8.函数内部运算和销毁

(1)函数的汇编代码

(2)图解

 9.总结

 10.解决问题

什么是函数栈帧?

 函数是如何调用的?

函数调用时参数时如何传递的?传参的顺序是怎样的?

 函数的形参和实参分别是怎样实例化的?

形参和实参又是什么样的关系呢?

 函数的返回值又是如何返回的?

 局部变量是如何创建的?

 为什么局部变量若不人为初始化,内容是随机的?

二.两个经典问题

1.汉诺塔

(1)背景

(2)图解

(3)移动次数

(4)代码实现

(5)打印步骤

2.青蛙跳台阶

(1)图解

(2)分析

(3)代码实现

结束语


本节课我们接上节的函数,继续来讲函数的递归中的栈帧,还有两个经典问题

一.栈帧

1.概念

每一个函数调用,都要在栈区创建个空间

函数栈帧(stack frame)就是函数调用过程中在程序的调用栈(call stack)所开辟的空间,这些空间是用来存放:

1、函数参数和函数返回值

2、临时变量(包括函数的非静态的局部变量以及编译器自动生产的其他临时变量)

3、保存上下文信息(包括在函数调用前后需要保持不变的寄存器)。

 (1) 栈

栈是一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后放入的数据被最先读出来)。

简单来讲你可以把栈理解为一个弹夹,而我们放的数据就像子弹,当我们射子弹时,总是会把后压入的弹先射出去,因为后压入的弹一定是放在最上面的,而先压入的弹后射出去,因为先压入的弹在最下面。这就是栈最大的特点"先入后出,后入先出",而往栈中放数据我们称作压栈(push),拿出栈中的数据我们叫出栈(pop)。

 (2)压栈push

 

 (3)出栈pop

 

2.了解寄存器

寄存器的功能是存储 二进制代码,它是由具有存储功能的 触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成

我们这节课需要知道的

eax (通用寄存器)通常用来执行加法,函数调用的返回值一般也放在这里面
ebx (通用寄存器)保留临时数据
eip (指令寄存器)最重要的寄存器,它指向了下一条要执行的指令所存放的地址
esp (通用寄存器)栈顶寄存器,指向栈的顶部
ebp (通用寄存器)栈底寄存器,指向栈的底部,通常用ebp+偏移量的形式来定位函数存放在栈中的局部变量

 我们最重要的看esp和ebp这两个,这两个寄存器是放地址的地方,这两个地址就是维护函数栈帧的地址寄存器。

简单来讲就是esp和ebp是两个指针,ebp指向当前栈帧栈底,esp指向函数栈栈顶。

 能看到,ebp并不是指向整个函数栈的栈底,而是指向当前栈帧的栈底,而由于esp总是指向栈顶,且栈只允许一个方向的操作,因此esp指向其实也是当前栈帧的栈顶,不过当前栈帧的栈顶始终与栈顶相同,因此说esp指向的是栈顶。

现在我们图解来看一下入栈和出栈

(1)入栈

(2)出栈

 

3.了解汇编指令

汇编指令是汇编语言中使用的一些操作符和 助记符,还包括一些 伪指令(如assume,end),汇编指令同机器指令一一对应。每一种CPU都有自己的汇编指令集。

我们这节课需要知道的

mov (通用数据传送指令)数据转移指令
push (通用数据传送指令)数据入栈,同时esp栈顶寄存器也要发生改变
pop (通用数据传送指令)数据弹出至指定位置,同时esp栈顶寄存器也要发生改变
sub (算术运算指令)减法
add (算术运算指令)加法
call (子程序调用指令)函数调用1. 压入返回地址 2. 转入目标函数
jump(无条件程序转移指令)通过修改eip,转入目标函数,进行调用
ret (子程序或函数返回指令)恢复返回地址,压入eip,类似pop eip命令

 4.main函数的调用

我们用加法代码来仔细分析

#include <stdio.h>
int Add(int x, int y)
{
	int z = 0;
	z = x + y;
	return z;
}
int main()
{
	int a = 10;
	int b = 20;
	int c = 0;
	c = Add(a, b);
	printf("%d\n", c);
	return 0;
}

 main 函数是被 __tmainCRTStartup 调用的,而这个函数是被 mainCRTStartup给调用

5.main函数栈帧的创建

(1)main汇编语言

int main()
{
003A18B0  push        ebp//在栈中压入ebp的值  
003A18B1  mov         ebp,esp//把esp的值给ebp  
003A18B3  sub         esp,0E4h//把esp的值减去0E4h  
003A18B9  push        ebx//在栈中压入ebx的值  
003A18BA  push        esi//在栈中压入esi的值  
003A18BB  push        edi//在栈中压入edi的值  
003A18BC  lea         edi,[ebp-24h]//把ebp-24h放入edi中  
003A18BF  mov         ecx,9//把9的值给ecx  
003A18C4  mov         eax,0CCCCCCCCh//把0CCCCCCCCh放入eax  
003A18C9  rep stos    dword ptr es:[edi]//从edi开始向下ecx的区域放入eax 

(2)图解

 6.变量的栈帧创建

(1)变量的汇编语言

    int a = 10;
003A18D5  mov         dword ptr [ebp-8],0Ah//在ebp-8位置处放入0Ah,即a的值  
	int b = 20;
003A18DC  mov         dword ptr [ebp-14h],14h//在ebp-14h位置处放入14,即b的值
    int c = 0;
003A18E3  mov         dword ptr [ebp-20h],0//在ebp-20h位置处放入0,即c的值 

(2)图解 

 

 7.函数传参

(1)传参的汇编语言

	c = Add(a, b);
003A18EA  mov         eax,dword ptr [ebp-14h]//把ebp-14h地址的值放入eax中  
003A18ED  push        eax//压入eax  
003A18EE  mov         ecx,dword ptr [ebp-8]//把ebp-8地址的值放入ecx中    
003A18F1  push        ecx//压入ecx   
003A18F2  call        003A10B4//调用add函数,栈顶保存call指令的下一条指令  
003A18F7  add         esp,8//形参销毁  
003A18FA  mov         dword ptr [ebp-20h],eax//形参销毁  

(2)图解

8.函数内部运算和销毁

(1)函数的汇编代码

int Add(int x, int y)
{
003A1770  push        ebp  
003A1771  mov         ebp,esp  
003A1773  sub         esp,0CCh  
003A1779  push        ebx  
003A177A  push        esi  
003A177B  push        edi  
003A177C  lea         edi,[ebp-0Ch]  
003A177F  mov         ecx,3  
003A1784  mov         eax,0CCCCCCCCh  
003A1789  rep stos    dword ptr es:[edi]  
003A178B  mov         ecx,3AC008h  
003A1790  call        003A131B  
	int z = 0;
003A1795  mov         dword ptr [ebp-8],0  
	z = x + y;
003A179C  mov         eax,dword ptr [ebp+8]  
003A179F  add         eax,dword ptr [ebp+0Ch]  
003A17A2  mov         dword ptr [ebp-8],eax  
	return z;
003A17A5  mov         eax,dword ptr [ebp-8]//把ebp-8的值放到eax寄存器中,让寄存器把结果带出函数  
}
003A17A8  pop         edi//弹出edi,同时esp地址增加  
003A17A9  pop         esi  
003A17AA  pop         ebx  
003A17AB  add         esp,0CCh  
003A17B1  cmp         ebp,esp  
003A17B3  call        003A1244  
003A17B8  mov         esp,ebp  
003A17BA  pop         ebp//通过ebp找回main的栈底  
003A17BB  ret

(2)图解

 (3)函数中的总结

1. 将main函数的 ebp 压栈

2. 计算新的 ebp 和 esp

3. 将 ebx , esi , edi 寄存器的值保存

4. 计算求和,在计算求和的时候,我们是通过 ebp 中的地址进行偏移访问到了函数调用前压栈进去的函数参数,这就是形参访问。

5. 将求出的和放在 eax 寄存器中准备带回

6.销毁Add函数栈帧,返回eax值

7.程序继续在main函数中运行

 9.总结

 最后我们放个完整的图解

    内存空间大小是固定的,所谓的开辟内存指的是把一块内存空间变为有效空间得以利用。

    用寄存器ebp和esp存储地址来进行内存管理,所谓的创建与销毁内存也是通过对ebp和esp存储的地址的改变来实现的,在ebp和esp之间的空间才是系统分配的空间,其他的都是无权限的空间。

 10.解决问题

什么是函数栈帧?

答:函数栈帧(stack frame)就是函数调用过程中在程序的调用栈(call stack)所开辟的空间,用以存放

1.函数参数和函数返回值

2.临时变量(包括函数的非静态的局部变量以及编译器自动生产的其他临时变量)

3.保存上下文信息(调用信息)。

 函数是如何调用的?

答:先传参,也就是把参数的值分别放在寄存器中,然后再push压入栈中;把主调函数ebp的值和下一条指令的地址push压入栈中,随后进入调用的函数中,创建函数栈帧并初始化,然后执行函数内的语句。

函数调用时参数时如何传递的?传参的顺序是怎样的?

答:其实传参就是把参数push到栈帧空间中,传参时先压入的是后面参数的值,(参数,参数,...)从右往左压入。

 函数的形参和实参分别是怎样实例化的?

(实例化一个对象就是为对象开辟内存空间)

 答:形参通过寄存器的值压栈创建,而实参通过 ebp 存储的地址进行偏移,由编译器决定一块未使用空间创建。

形参和实参又是什么样的关系呢?

 答:形参是实参的一份临时拷贝,改变形参不会影响实参。

 函数的返回值又是如何返回的?

 答:通过寄存器保留副本,不会随栈帧销而销毁,毁待函数调用完栈帧销毁后把寄存器的值拷贝到主调函数中对应的变量里,实现返回值的带回。

 局部变量是如何创建的?

 答:局部变量是在局部变量所在函数的栈帧空间中创建的,通过 ebp 存储的地址进行偏移,由编译器决定一块未使用空间创建。

 为什么局部变量若不人为初始化,内容是随机的?

答:函数栈帧创建后会自动将空间中存储的值全部初始化为一个特定值(如VS2019下为0xcccccccc),编译器不同值也不同。

借鉴博主: 蒋灵瑜的笔记本 


二.两个经典问题

1.汉诺塔

(1)背景

汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。(源自百度百科)

(2)图解

 (3)移动次数

我们可以分析一下,从3层的,往上数,找出里面的规律

 阶数次数规律
112^1-1
232^2-1
372^3-1
4152^4-1
..........2^n-1

对于n阶汉诺塔的移动次数:

  • 步骤1所含步数就是n-1个圆盘移动所需的次数,我们可以将其步数看做f(n-1)。
  • 步骤2所含步数为1。
  • 步骤3所含步数与步骤1相似,我们也将其步数看做f(n-1)。

 再观察表格中汉诺塔的移动次数,对于一阶汉诺塔移动次数就为1,对于其他的阶数则为前一阶汉诺塔移动次数 + 1 + 前一阶汉诺塔移动次数。

我们就能得出表达式:f(n-1) + 1 + f(n-1) = 2 * f(n - 1) + 1

(4)代码实现

#include<stdio.h>
int hanoi_step(int n)
{
	if(n<=1)
		return 1;
	else
		return 2*hanoi_step(n-1)+1;
}
int main()
{
	int n = 0;
	scanf("%d",&n);
	int ret = hanoi_step(n);
	printf("%d\n",ret);
	return 0;
}

得出几阶的需要移动几次

(5)打印步骤

我们还是类比来写,我们写出前四阶的来看,分析后面的

阶数步骤
1A->C
2A->B,A->C,B->C
3A->C,A->B,C->B,A->C,B->A,B->C,A->C
4A->B,A->C,B->C,A->B,C->A,C->B,A->B,A->C,B->C,B->A,C->A,B->C,A->B,A->C,B->C

我们观察移动步骤,发现只有一个圆盘时移动步骤为A->C;两个圆盘时,为A->B,A->C,B->C。

那么对于n阶汉诺塔呢,我们对其进行推演:

把n-1个圆盘从A移动到B
把第n个圆盘从A移动到C
把n-1个圆盘从B移动到C


那n-1个圆盘如何从A移动到B呢?

把n-2个圆盘从A移动到C
把第n-1个圆盘从A移动到B
把n-2个圆盘从C移动到B


同样的,对于把n-1个圆盘从B移动到C,也可以推测出来:

把n-2个圆盘从B移动到A
把第n-1个圆盘从B移动到C
把n-2个圆盘从A移动到C

但是这样很难理解,我们化为具体的数字,我们化为64

步骤1、通过一种符合要求的方式将A柱上63个圆盘从A移动到B(我们不要关心这个方式具体是什么)
步骤2、经过步骤1之后A柱上只剩下一个圆盘,我们将这个圆盘从A移动到C(我们所要关心的只有最后将1个圆盘从A移动到C)
步骤3、经过步骤1和步骤2之后,B柱上有了63个圆盘,C上有1个圆盘,我们再通过某种方式将B柱上63个圆盘从B移动到C(同样也不要关心这个具体的方式是什么)
经过了步骤1、 2 、3之后,我们就将所有的圆盘从A移动到了C
 

步骤1又可以继续拆分:
步骤1.1、将62个圆盘从A柱移动到C柱
步骤1.2、将1个圆盘从A柱移动到B柱
步骤1.3、将62个圆盘从C柱移动到B柱

步骤1.1又可以继续拆分:
1.1.1、将61个圆盘从A柱移动到B柱
1.1.2、将1个圆盘从A柱移动到C柱
1.1.3、将61个圆盘从B柱移动到C柱
继续向下拆分
.
.
.
经过63次拆分后,第64次只需要移动1个圆盘,只需要将1个圆盘移动到领一个圆盘上即可,所以我们就能递归来写

思路:定义A,B,C三个字符,表示A,B,C三柱,定义n为阶数,那么n-1也就是移动步骤中,需要移动的圆盘数。
对于一阶汉诺塔,直接移动即可,对于其他的阶数,则需要通过递归展开,为n阶汉诺塔的移动步骤。

#include<stdio.h>
void hanoi_move(int n,char A,char B,char C)
{
	if(1==n)
	{
		printf("%c->%c\n",A,C);
	}
	else
	{
		hanoi_move(n-1,A,C,B);//将n-1个圆盘从A移动到B
		printf("%c->%c\n",A,C);//将第n个圆盘从A柱移动到C柱
		hanoi_move(n-1,B,A,C);//将n-1个圆盘从B柱移动到C柱
	}
}
int main()
{
	int n = 0;
	scanf("%d",&n);
	hanoi_move(n,'A','B','C');
	return 0;
}

 我们来画个图,然后再用俗话给大家讲一下。

 我们用俗话说一下,我们用下面这个来说

这里可能代码不好理解,我们分开写为两代码

#include<stdio.h>

void Move_(char From, char Dest)					//移动一个圆盘,将圆盘从来源移动到目的地  从From 移动到Dest 
{
	printf("将一个圆盘从%c柱子 -> %c柱子\n", From, Dest);
}
void Hanoi( char A,char B,char C,int  n)	//总共有n个圆盘,将这n个圆盘  借助 B 柱子 从 A 柱子移动到  C 柱子
{
	if (n == 1)								//当只有一个圆盘时,直接圆盘从 A 柱 移动到 C 柱
	{
		Move_(A, C);
	}
	else  
	{
		Hanoi(A,C,B,n - 1);				 //当不只一个圆盘时,我们先将上面 (n -1)个圆盘 借助 C柱子  从 A 柱子移动到 B 柱子

		Move_(A, C);					//A柱剩余一个圆盘,将剩下的一个圆盘从 A 移动到 C
		Hanoi(B, A, C, n - 1);			//再将(n-1)个圆盘 借助 A柱子 从 B柱子 移动到 C柱子
	}
}
int main()
{
	
	int  n = 0;							//汉诺塔层数
	char A = 'A';						//A柱子
	char B = 'B';						//B柱子
	char C = 'C';						//C柱子
	scanf("%d", &n);

	Hanoi(A,B,C,n);						//将n个圆盘,借助于B柱子,从A柱子移动到C柱子
	return 0;
}

Hanoi(A,C,B,n - 1);               

Move_(A, C);                  
Hanoi(B, A, C, n - 1);    

我们就看这三步,我们把这个问题就是想成,A上的最下面的是n,上面的都是n-1,我们就是要把这n-1个借助C来放到B上,所以我们的代码就是ACB

然后我们第二步就是,把A上的那个最下面的n放到C上去,所以我们的代码就是AC

然后我们第三步就是,把B上的n-1,借助于A放到现在C最大的n的上面,所以我们的代码就是BAC

这就是我们的递归,n-1上面的重复这个过程,就解决了我们的这个问题。

2.青蛙跳台阶

一只青蛙一次最少可以跳跃1级台阶,一次最多可以跳跃2级台阶,求:该只青蛙跳上n级台阶共有多少种跳跃方法?

其实这道题你分析完会发现就是很像斐波那契数列,我们来一步一步分析

(1)图解

 (2)分析

我们发现我们知道前两个跳台阶的方法数,加一起就是第三种台阶的跳法

加入我们求跳n阶台阶的方法数,n=(n-1)+(n-2);

(3)代码实现

#define _CRT_SECURE_NO_WARNINGS
 
#include <stdio.h>
 
int JumpFloor3(int n)
{
	int an = 0;
	int a1 = 1;
	int a2 = 2;
	if (n == 1)   //第1级台阶,青蛙有1种跳跃方法
	{
		an = a1;
	}
	else if (n == 2)   //第2级台阶,青蛙有2种跳跃方法
	{
		an = a2;
	}
	else   //第2级往后台阶,跳跃方法种数为前两级跳跃方法总数之和
	{
		int i;
		for (i = 3; i <= n; i++)
		{
			an = a1 + a2;
			a1 = a2;
			a2 = an;
		}
	}
	return an;
}
int main()
{
	int x;          //总共需要跳的台阶级数
	printf("请输入青蛙总共需要跳跃的台阶级数:");
	scanf("%d", &x);
	int count = JumpFloor3(x);      //调用青蛙跳台阶函数解决问题
	printf("一只青蛙要跳上%d级的台阶,每次跳跃1或2级,共有%d种跳跃方法\n", x, count);   //输出结果
	return 0;
}

这个还是相对于汉诺塔相对简单的,我们认真分析里的递归就可以

结束语

这节课讲了栈帧,不好理解,多看多演示,还有两个经典递归,递归的思想就是可以重复的倒着推演,下节课我们讲数组,记得关注!!!

赫洋同学
关注 关注
  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
c语言-阶乘算法(迭代和递归).docx
12-16
C语言-阶乘算法是计算阶乘的经典算法,包括迭代算法和递归算法两种实现方式。阶乘是数学中的一种运算符号,表示一个数字的所有正整数因子的乘积,如n! = n * (n-1) * (n-2) * (n-3) * ... * 1。其中,0的阶乘定义为1...
函数调用是什么
最新发布
林隐的博客
02-05 767
函数调用是什么
图解分析Hanoi Tower(汉诺塔)程序
白水的博客
12-26 5712
汉诺塔程序伪算法:将 n 个盘子从 A 塔移动到 C 塔 分解为以下步骤: 1、将 A 塔上 n-1 个盘子借助 C 塔先移动到 B 塔; 2、将 A 塔剩下的第 n 个盘子移动到 C 塔; 3、将 B 塔上的 n-1 个盘子借助 A 塔移动到 C 塔;以下是代码:#include "stdio.h"void move(char from, char target) { printf
与队列】求解汉诺塔问题(1.用递归的方式)
hekaikai666的博客
09-08 1143
功能需求 事先声明:博主在一本算法书上看到这个问题,对此有一些想法,有一部分出自抄腾,博主一心想表达自己对于处理问题的观点.对于此无需注明转发出处.此汉诺塔问题递归算法并未解决柱子还原之前不能为空问题,此种方法还有待优化.         汉诺塔问题一直是数据算法结构中比较经典的一个问题,但是还需要略微解释一下:相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置...
3.函数(递归+栈帧
admire_999的博客
08-26 610
详细介绍函数的定义以及使用 并对函数栈帧的创建和销毁进行了图示详解
【数据结构】递归
Tracier的博客
10-25 223
5.全排列:首先知识点——排列组合,排列的定义:从n个不同元素中,任取m(m≤n,m与n均为自然数,下同)个元素按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列;从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。初始时n个空位,先填第一个空位,第一个空位可以填的数据有三种,每一种往下填第二个空位,第二个空位可以填的数据有两种,以此往下类推。的序列,序列中无相同元素,且每个元素都是长度为n位的二进制位串,相邻元素恰好只有1位不同。
C语言速记——基本内容
10-02
C语言的创建过程包括编辑、编译、链接和执行四个步骤。编辑阶段,开发者使用文本编辑器创建源代码文件。编译阶段,编译器将源代码转换为机器语言,检查语法错误,并生成对象文件。链接阶段,链接器合并多个对象文件...
java算法——汉诺塔经典递归
07-15
汉诺塔——经典递归 *实现移动函数 *递归实现汉诺塔函数
C语言18个经典程序C语言18个经典程序.docx
11-12
该程序使用了两个数组a和b来存储原始数组和旋转后的数组,然后使用一个for循环来将原始数组的元素赋值给旋转后的数组。 第六个程序是打印直角杨辉三角形。该程序使用了一个二维数组来存储杨辉三角形的元素,然后...
C语言函数的递归和调用实例分析
01-20
 C语言中的函数可以递归调用,即:可以直接(简单递归)或间接(间接递归)地自己调自己。 要点: 1、C语言函数可以递归调用。 2、可以通过直接或间接两种方式调用。目前只讨论直接递归调用。 二、递归条件  ...
C语言进阶】函数栈帧与可变参数列表(函数调用,函数栈帧,可变参数列表,递归调用)
52Herzt的博客
11-30 1754
函数调用,函数栈帧,可变参数列表,递归调用
C语言函数递归例题讲解(超详细~)
m0_63564767的博客
08-22 695
由图中我们可以看出,当用户输入1729的值后,函数将层层递推下去,直到n的值少于10,也就是DigitSum(1)时,返回的值为1,接着又向上层层回归上去,并且把该层。由图我们可以看出,当我们要求Fun(2)的值时,程序会先进入到else的那层分支语句里面,然后逐层递推下去,直到n==5时,返回2,也就是。的终止条件是什么呢,细心的话,我们可以发现当k=1时, 3^1=3,则返回的是n它本身的值,也就是。返回的是3,然后再逐层往上回归,直到我们把Pow(3,4)的值求出来,那么递归才结束。
C语言】函数递归及其经典案例(汉诺塔等)
m0_75219751的博客
08-15 1343
该文章将详细讲述函数递归的思考方式,以及解决汉诺塔,青蛙跳台阶等问题
干诺塔问题的原理图解及实现
qq_41594050的博客
01-27 384
一、汉诺塔问题 如下图所示,从左到右有A、B、C三根柱子,其中A柱子上面有从小叠到大的n个圆盘,现要求将A柱子上的圆盘移到C柱子上去,期间只有一个原则:一次只能移到一个盘子且大盘子不能在小盘子上面,求移动的步骤和移动的次数 (1)n == 1       第1次 1号盘 A---->C sum = 1 次 (2) n == 2       第1次 1...
汇编学习教程:关于,遗留的问题
奋进的代码
02-22 1488
引言 在我们这几篇内存访问的博文中,你会发现这个东西,关于它的讲解占了差不多有一半左右,足以见识到它的重要性。随着我们后面深入学习,你会发现在开发中往往承担了很重要的角色,所以我们势必要好好学习,彻底把它搞明白。 在上篇博文中,我们已经学习了两个操作的指令,分别是:PUS、POP,学习了两个访问需要的寄存器,分别是:SS段寄存器、SP寄存器。我们通过在Debug上进行实际操作和观察内存数据变化,明白了PUSH、POP指令背后,CPU都做了什么样的工作。 那么本篇博文,我们将探讨一些遗留的问
数据结构(C语言版)之递归
m0_57859086的博客
10-26 7813
前言 ●数据结构作为计算机专业基础课,综合性强,抽象性高,在一定程度上增加了学习难度,本次我们共同从数据结构的基础探讨,由浅入深进行数据结构的学习。 ●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教! ●本文只浅显的探讨了的基本知识,作者相信随着学习课程的深入,我们将会对数据结构有更深的理解与收获!
数据结构(三)递归
b13766339702的博客
02-01 554
的定义   是限制在表的一端进行插入和删除的线性表。允许插入、删除的这一端称为顶,另 一个固定端称为底。当表中没有元素时称为空顶:通常将表中允许进行插入、删除操作的一端称为顶 (Top),因此顶的当前位 置是动态变化的,它由一个称为顶指针的位置指示器指示。 底:同时表的另一端被称为底 (Bottom)。当中没有元素时称为空的插入 操作被形象地...
【数据结构(14)】3.4 递归
shangguanxiu的博客
12-30 897
严蔚敏版【数据结构】1. 递归的定义。 2. 常用到递归的3种情况。 3. 递归问题—用分治法求解。 4. 函数调用过程。 5. 递归的特点。 6. 递归转非递归
嵌入式系统中堆heap和stack的管理——如何计算stack size
liangxh的博客
12-05 6134
程序运行的各种存储段分类 程序运行时在内存中主要有代码段、数据段、堆段(堆空间和空间)、进程头、动态链接库等区域。 其中数据使用到的段包括 数据段:静态内存空间,其中数据的总大小和初始值在编译时确定,数据在整个程序运行时一直存在。 空间:自动内存空间,其中数据的大小在编译时确定,数据的分配和释放也由编译器在函数进入和退出时插入指令完成,数据生命周期和函数一样。 堆...
C语言编程疑惑解答——495个经典问题解析
"《你必须知道的495个C语言问题》是一本关于C语言细节问题的集合,由Steve Summit原著,朱群英和孙云翻译,2005年的修订版为0.9.4。这本书涵盖了C语言中的各种常见问题,包括声明和初始化、结构、联合和枚举等主题,...
写文章

热门文章

  • C语言初阶——循环语句 4364
  • C语言初阶——调试技巧 2019
  • C语言初阶——三子棋(细节狂魔) 1627
  • C语言进阶——字符函数 1474
  • C语言初阶——猜数字等等 1361

最新评论

  • C语言初阶——调试技巧

    m0_74281148: 大佬🧍‍♂️

  • C语言初阶——操作符part2

    Billow_Z: 支持佬表情包表情包

大家在看

  • 微服务 OMS 系统如何推动企业B2B业务和DTC业务协同创新|商派 550
  • 设计资料:4通道1G PCIE3.0X8采集平台 233
  • cadence virtuoso 修改电路原理图schematic背景颜色以及格点
  • MySQL 【正则表达式】函数大全
  • npm install一直下载失败,也不知道是什么原因造成的,已经弄过证书验证了,还是没有用....哪位大神可以帮帮忙

最新文章

  • JavaSE——数组
  • JavaSE——方法的使用
  • JavaSE——逻辑控制
2023年15篇
2022年20篇

目录

目录

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

玻璃钢生产厂家阜阳学校玻璃钢雕塑大猩猩玻璃钢雕塑荷叶玻璃钢卡通雕塑定制浙江中庭商场美陈供应商四川玻璃钢树造型雕塑小品制作美陈玻璃钢动物雕塑供应商家人物玻璃钢雕塑图片河北大型商场美陈江苏玻璃钢雕塑厂招聘甘肃玻璃钢雕塑浮雕景观玻璃钢雕塑供应商玻璃钢几何鹿动物雕塑定做杭州户外玻璃钢花箱花盆玻璃钢商场吉祥物雕塑衢州商场开业美陈南昌玻璃钢人物雕塑制作厂家制作大型玻璃钢雕塑厂家北京玻璃钢卡通雕塑羊甘肃玻璃钢雕塑尺寸脱色玻璃钢雕塑翻新的处理方法闵行商场美陈扬州玻璃钢雕塑报价明细表烤漆玻璃钢雕塑批发韶关玻璃钢卡通雕塑商场店庆美陈及活动平罗玻璃钢雕塑制作招远玻璃钢雕塑哈尔滨玻璃钢花盆雕塑常州黑色玻璃钢花盆萍乡多彩玻璃钢雕塑价位香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化