c语言顺序栈函数调用 顺序栈的主函数c语言

C语言函数调用栈程序的执行过程可看作连续的函数调用 。当一个函数执行完毕时,程序要回到调用指令的下一条指令(紧接call指令)处继续执行 。函数调用过程通常使用堆栈实现,每个用户态进程对应一个调用栈结构(call stack) 。编译器使用堆栈传递函数参数、保存返回地址、临时保存寄存器原有值(即函数调用的上下文)以备恢复以及存储本地局部变量 。
不同处理器和编译器的堆栈布局、函数调用方法都可能不同 , 但堆栈的基本概念是一样的 。
寄存器是处理器加工数据或运行程序的重要载体,用于存放程序执行中用到的数据和指令 。因此函数调用栈的实现与处理器寄存器组密切相关 。
AX(AH、AL):累加器 。有些指令约定以AX(或AL)为源或目的寄存器 。输入/输出指令必须通过AX或AL实现 , 例如:端口地址为43H的内容读入CPU的指令为INAL , 43H或INAX , 43H 。目的操作数只能是AL/AX,而不能是其他的寄存器 。[5]
BX(BH、BL): 基址寄存器。BX可用作间接寻址的地址寄存器和 基地址寄存器 , BH、BL可用作8位通用数据寄存器 。[5]
CX(CH、CL):计数寄存器 。CX在循环和串操作中充当计数器,指令执行后CX内容自动修改,因此称为计数寄存器 。[5]
DX(DH、DL):数据寄存器 。除用作通用寄存器外,在 I/O指令 中可用作端口 地址寄存器 ,乘除指令中用作辅助累加器 。[5]
2.指针和 变址寄存器
BP( Base Pointer Register):基址指针寄存器 。[5]
SP( Stack Pointer Register): 堆栈指针寄存器。[5]
SI( Source Index Register):源变址寄存器 。[5]
DI( Destination Index Register):目的变址寄存器 。[5]
函数调用栈的典型内存布局如下图所示:
图中给出主调函数(caller)和被调函数(callee)的栈帧布局,"m(雙)"表示以EBP为基地址、偏移量为m字节的内存空间(中的内容) 。该图基于两个假设:第一 , 函数返回值不是结构体或联合体,否则第一个参数将位于"12(雙)" 处;第二,每个参数都是4字节大小(栈的粒度为4字节) 。在本文后续章节将就参数的传递和大小问题做进一步的探讨 。此外,函数可以没有参数和局部变量 , 故图中“Argument(参数)”和“Local Variable(局部变量)”不是函数栈帧结构的必需部分 。
其中,主调函数将参数按照调用约定依次入栈(图中为从右到左),然后将指令指针EIP入栈以保存主调函数的返回地址(下一条待执行指令的地址) 。进入被调函数时,被调函数将主调函数的帧基指针EBP入栈,并将主调函数的栈顶指针ESP值赋给被调函数的EBP(作为被调函数的栈底),接着改变ESP值来为函数局部变量预留空间 。此时被调函数帧基指针指向被调函数的栈底 。以该地址为基准,向上(栈底方向)可获取主调函数的返回地址、参数值,向下(栈顶方向)能获取被调函数的局部变量值 , 而该地址处又存放着上一层主调函数的帧基指针值 。本级调用结束后,将EBP指针值赋给ESP,使ESP再次指向被调函数栈底以释放局部变量;再将已压栈的主调函数帧基指针弹出到EBP,并弹出返回地址到EIP 。ESP继续上移越过参数,最终回到函数调用前的状态,即恢复原来主调函数的栈帧 。如此递归便形成函数调用栈 。
EBP指针在当前函数运行过程中(未调用其他函数时)保持不变 。在函数调用前 , ESP指针指向栈顶地址,也是栈底地址 。在函数完成现场保护之类的初始化工作后,ESP会始终指向当前函数栈帧的栈顶,此时,若
C 语言:调用函数时,函数参数压入堆栈的顺序:从左到右还是从右到左?标准C参数压栈次序是反向压栈,也就是从右到左 。因为C要把不定参数...放在最右边 , 为了高效率定位参数,所以只能从右到左压栈,这样第一个参数最靠近栈顶 。
比如printf
(const
char
*
szFormat,...);如果从左到右压不容易找到第一个参数szFormat
不过16位操作系统的时候 , 调用API函数时,微软的vc曾经支持过一种从左到右的压占次序,现在32位系统没有了 。
关于C语言的顺序栈的操作这是我以前写的,今天不想砍代码,就发这个了
#includestdio.h
#includestdlib.h
#define N 100
//栈的结构定义
typedef struct
{
int elem[N];
int top;//栈顶
}Stack;
//循环队列的结构定义
typedef struct
{
int elem[N];
int front;
int rear;
}Queue;
int Greatstack(Stack*);
int GreatQueue(Queue *);
int pop(Stack *s);
void show(Stack*s);
int push(Stack *s);
int popStack(Stack *s);
int enQueue(Queue *q);
int deQueue(Queue *q);
int printQueue(Queue *q);
void conversion();
void main()
{
char exit='N';
int ch;
int result,data;
int m,e;
Stack s;
Queue q;
s.top=0;//栈顶指向当前栈顶的下一位置
q.front=q.rear=0;
do
{
system("CLS");
printf("\t\t********************************************\n");
printf("\t\t*1.创建一个顺序栈.................(1)*\n");
printf("\t\t*2.出栈.............................(2)*\n");
printf("\t\t*3.入栈.............................(3)*\n");
printf("\t\t*4.顺序栈中元素依次出栈,并显示.....(4)*\n");
printf("\t\t*5.创建一个循环队列.................(5)*\n");
printf("\t\t*6.进队.............................(6)*\n");
printf("\t\t*7.出队.............................(7)*\n");
printf("\t\t*8.循环队列中元素依次出队 , 并显示...(8)*\n");
printf("\t\t*9.十进制数转换为其它进制数.........(9)*\n");
printf("\t\t*10.退出..............(10) *\n");
printf("\t\t********************************************\n");
printf("\n请选择操作代码:");
scanf("%d",ch);
switch(ch)
{
case 1:
printf("创建一个顺序栈\n");
result=Greatstack(s);
if(result==0)printf("顺序栈创建失败,栈已满!\n");
else printf("顺序栈创建成功!\n");
system("pause");
break;
case 2:
printf("出栈:\n");
m=pop(s);
if(m==0)printf("出栈失败,栈已空!\n");
else
{
printf("顺序栈出栈成功!\n");
printf("该栈剩余元素为:");
show(s);
}
//请加入出栈操作的代码或函数调用
system("pause");
break;
case 3:
printf("进栈:\n");
printf("请输入入栈的元素");
scanf("%d",e);
result=push(s,e);
if(result==0)printf("栈已满!\n");
else
{
printf("顺序栈入栈成功!\n");
printf("该栈剩余元素为:");
show(s);
}
//请加入进栈操作的代码或函数调用
system("pause");
break;
case 4:
printf("顺序栈中元素依次出栈 , 出栈序列为:\n");
popStack(s);
//请加入依次出栈并显示元素操作的代码或函数调用
system("pause");
break;
case 5:
printf("创建一个循环队列\n");
result=GreatQueue(q);
if(result==0)printf("循环队列创建失败,循环队列已满!\n");
else printf("循环队列创建成功!\n");
system("pause");
break;
case 6:
printf("入队:\n");
data=https://www.04ip.com/post/enQueue(q);
if(result=0) printf("队已经满了\n");
else printf("入队成功\n");
//请加入入队操作的代码或函数调用
system("pause");
break;
case 7:
printf("出队:\n");
data=https://www.04ip.com/post/deQueue(q);
if(data=https://www.04ip.com/post/0) printf("队已经空了\n");
else printf("出队成功\n");
//请加入依次出队操作的代码或函数调用
system("pause");
break;
case 8:
printf("循环队列中元素依次出队,出队序列为:\n");
//请加入依次出队并显示元素操作的代码或函数调用
data=https://www.04ip.com/post/printQueue(q);
system("pause");
break;
case 9:
printf("十进制数转换为其它进制数:\n");
conversion();
//请加入十进制数转换为其它进制数操作的代码或函数调用
system("pause");
break;
case 10:
getchar();
printf("\n您是否真的要退出程序(Y/N):");
exit=getchar();getchar();
break;
default:
printf("\n无效输入 , 请重新选择...:");
}
}while(exit!='y'exit!='Y');
}
/*从键盘输入一系列整数 , 当输入值为0时 , 停止输入,产生顺序栈*/
/*返回0表示生成成功,1表示失败*/
int Greatstack(Stack*s)
{
int e;
s-top=0;//栈顶指向当前栈顶的下一位置
printf("请依次输入需要入栈的元素,以0表示输入结束:");
do
{
scanf("%d",e);
if(e!=0)
{if(s-top=N)return 0;//栈满
s-elem[s-top]=e;
}
}while(e!=0);
}
/*从键盘输入一系列整数,当输入值为0时,停止输入,产生循环队列*/
/*返回0表示生成成功,1表示失败*/
int GreatQueue(Queue*q)
{
int e;
q-front=q-rear=0;//初始化队列
printf("请依次输入需要入栈的元素,以0表示输入结束:");
do
{
scanf("%d",e);
if(e!=0)
{if((q-rear 1)%N==q-front)return 0;//队满
q-elem[q-rear]=e;
q-rear=(q-rear 1)%N;
}
}while(e!=0);
return 1;
}
int pop(Stack *s)//出栈
{
if(s-top==0)
return 0;
--s-top;
}
void show(Stack*s)//显示栈中的元素
{
int i=s-top;
while(i!=0)
{
--i;
printf("%d ",s-elem[i]);
}
}
int push(Stack *s,int e)//入栈
{
if(s-top=N)return 0;
s-elem[s-top]=e;
}
int popStack(Stack *s)//顺序栈中元素依次出栈,并显示
{
while(s-top!=0)
{
--s-top;
printf("=",s-elem[s-top]);
}
return 0;
}
int enQueue(Queue *q)//入队
{
int e;
printf("请输入入栈的元素:");
scanf("%d",e);
if((q-rear 1)%N == q-front) return 0;
q-elem[q-rear]=e;
q-rear=(q-rear 1)%N;
return 1;
}
int deQueue(Queue *q)//出队
{
int *e;
if(q-front == q-rear) return 0;
e =q-elem[q-front];
q-front=(q-front 1)%N;
return 1;
}
int printQueue(Queue *q) //循环队列中元素依次出队 , 并显示
{
if(q-front == q-rear) return 0;
for(;q-front!=q-rear;)
{
printf("=",q-elem[q-front]);
q-front;
}
}
void conversion()//十进制数转换为其它进制数
{
Stack p1;
int n,m;
puts("请输入需要转换的元素:");
scanf("%d",n);
puts("请输入需要转换的进制:");
scanf("%d",m);
p1.top=0;
while(n)
{
push(p1,n%m);
n=n/m;
}
popStack(p1);
}
c语言怎么调用栈函数给你个例子:
#include
//写好加法,以便调用
int sum(int x1,int x2)
{
int x3=x1 x2;
return x3;
}
void main()
{
int a=0;
int b=0;
int c=0;
printf("请输入两个整数\n");
scanf("%d%d",a,b);
c=sum(a,b);//传递参数给sum()函数,返回他们的和
printf("%d %d的和是:%d\n",a,b,c);
}
总之:就是你把一种方法写到单独的块,这里就是sum()函数,执行一个单一的功能 , 在main函数调用就是了!
【c语言顺序栈函数调用 顺序栈的主函数c语言】关于c语言顺序栈函数调用和顺序栈的主函数c语言的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站 。

    推荐阅读