栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

(C语言)函数栈帧&可变参数列表&命令行参数

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

(C语言)函数栈帧&可变参数列表&命令行参数

一 函数栈帧

1.认识相关寄存器

eax:通用寄存器,保存临时数据,常用于返回值。

ebx:通用寄存器,保存临时数据。

ebp:栈底寄存器。

esp: 栈顶寄存器。

eip: 指令寄存器,保存当前指令的下一条指令的地址。

2.认识相关汇编命令

mov: 数据转移指令

push: 数据入栈,同时esp栈顶寄存器也要发生改变。

pop:数据弹出至指定位置,同时esp栈顶寄存器也要发生改变。

sub:减法命令。

add: 加法命令。

call:函数调用,①压入返回地址。②转入目标函数。

jump:通过修改eip,转入目标函数,进行调用。

ret:恢复返回地址,压入eip,类似pop eip 命令。

3.函数栈帧总结

1.临时变量的形成是在函数正式被调用之前就形成了的。

2.形参实例化的顺序是从右向左的。

3.函数调用完毕,栈帧结构被释放。

4.临时变量具有临时性的本质:栈帧具有临时性。

5.调用函数是有成本的,成本体现在时间和空间上,本质是形成与释放栈帧有成本。

6.函数调用,因拷贝所形成的临时变量,变量和变量之间的位置关系是有规律的。

二 可变参数列表

1.注意事项

可变参数必须从头到尾逐个访问。如果你在访问了几个可变参数之后想半途终止,这是可以的,但是,如果你想一开始就访问参数列表中间的参数,那是不行的。参数列表中至少有一个命名参数。如果连一个命名参数都没有,就无法使用 va_start 。这些宏是无法直接判断实际存在参数的数量。 这些宏无法判断每个参数的是类型。如果在 va_arg 中指定了错误的类型,那么其后果是不可预测的

2.原理

先看看这几个宏的含义: 1. 可变参数列表对应的函数,最终调用也是函数调用,也要形成栈帧 2. 栈帧形成前,临时变量是要先入栈的,根据之前所学,参数之间位置关系是固定的 3. 通过上面汇编的学习,发现了短整型在可变参数部分,会默认进行整形提升,那么函数内部在提取该数据的时候,就要考虑提升之后的值,如果不加考虑,获取数据可能会报错或者结果不正确。
#include
#include

//查找最大数据。
int FindMaxDate(int num, ...)
{
	va_list arg;    //定义可以访问可变参数部分的变量,其实是一个char*类型
	va_start(arg,num);   //使arg指向可变参数部分
	int max = va_arg(arg, int);  //根据类型,获取可变参数列表中的第一个数据
	for (int i = 0; i < num - 1; i++)//获取并比较其他的
	{
		int curr = va_arg(arg, int);
		if (max < curr)
		{
			max = curr;
		}
	}
	va_end(arg);//arg使用完毕,收尾工作。本质就是讲arg指向NULL
	return max;
}


int main()
{
	int max = FindMaxDate(5,1,2,5,4,9);
	printf("%dn", max);
	return 0;
}
三  命令行参数

1.main函数也是可以带参数的。

#include  
int main(int argc, char* argv[], char* envp[]) 
{ 
    int i = 0; 
     for(i=0; i

argc: 是个整型变量,表示命令行参数的个数(含第一个参数)。

argv :是个字符指针的数组,每个元素是一个字符指针,指向一个字符串。这些字符串就是命令行中的每一个参数(字符串)。

envp :是字符指针的数组,数组的每一个原元素是一个指向一个环境变量(字符串)的字符指针。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/947809.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号