兰泽又多芳草,可变参数列表

Posted 乔乔家的龙女仆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了兰泽又多芳草,可变参数列表相关的知识,希望对你有一定的参考价值。

传统艺能😎

小编是大一菜鸟不赘述,欢迎大佬指点江山(QQ:1319365055)
此前博客点我!点我!请搜索博主 【知晓天空之蓝】
乔乔的gitee代码库(打灰人欢迎访问,点我!

过渡区🤣

现在是北京时间13:15,期末考试结束,明天卷铺盖回家喽!yysy,算见识了嘛是卷翻天,博客之星20s没见就给降了一名,睡一觉起来各位都是一万多总分,泪,6 了下来。我放假了各位,键盘不烂我不睡好吧

正片开始👀

可变参数👏

可变参数是C语言提供的一种参数可变的机制,咱希望函数带有可变数量的参数,而不是预定义数量的参数。它允许咱定义一个函数,能根据具体的需求接受可变数量的参数,比如这种:

int Max(int num,...)

 va_list arg;
 va_start(arg,num);
 int max = va_arg(arg,int);
 for(int i = 1;i<num;i++)
 
 int sid = va_arg(arg,int);
 
 if(sid > max)
 
 max = sid;
 
 va_end(arg);
 return max; 


int main()

int a = Max(5,1,2,3,4,5);
printf("%d\\n",a);
return 0;


如上形式Max函数就用到了可变参数,注意!使用可变参数时,Max内首元素 ‘ 5 ’代表元素个数

那么问题来了,如果函数没有形式参数,可以给函数传递吗?答案是可以的,在C语言中,只要发生了函数调用并调用了参数,必定会形成临时变量;所谓临时拷贝(变量)的本质,也就是在栈帧内部形成的(从右向左形成临时拷贝(变量)).

宏观过程👏

va_list定义了可以访问可变参数部分的变量,他的本质是一个 char 类型指针。va_start 使 b 指向可变参数部分,va_end 是用来完成收尾工作的,本质就是将参数arg置为空,避免野指针。

掐头去尾,我们看看主体部分。首先 arg 指针先让我的数据入栈,我们打开反汇编能看到栈顶 esp 位置,再在内存窗口找到 esp 位置,就会看到这个经典的一幕,倒着入栈连着几个数据入栈是压在一起的,这种结构对我们查找元素就非常友好了。

宏观的框架就是我们传入的变量 num 就代表第一个参数 5,va_start 就是让 arg 原本指向5的 ,再让他指向有效部分,比如 1,根据指向 1 的起始地址, va_start 指向他的可变部分(去掉已指向的有效部分),具体如何实现见下文;最后 va_arg 就是根据类型 int ,从起始地址开始连续读取找到某一个元素,这样最终会把所需要的 max 的值读出来。

原理👏

可变参数列表对应的函数,最终调用也是函数调用,也要形成栈帧,栈帧形成前,临时变量会先入栈,根据咱之前总结的,参数位置都是相对固定的;在可变参数中 ,如果是短整型,一般都要进行整型提升,比如参数传入的是 char 类型,但实际传出的是 int 类型,这就是我们的 va_arg(arg,int)为什么是 int 而不是 char,所以在 va_arg 中指定了错误的类型,那结果无法预测。

要注意:
1.可变参数必须从头到尾逐个进行访问,如果你访问了几个可变参数后想半途而废,是可以做到的,但如果一开始就想访问中间某个元素的话,哒咩!
2.参数列表中至少有一个命名参数,如果连一个参数都没有,就没办法使用 va_start;
3.这些宏是没办法直接判断实际存在的参数数量的,也无法判断每个参数的类型

格局打开👏

#define _crt_va_start(ap,v)  (ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)
#define _crt_va_arg(ap,t)  (*(t*)((ap += _INTSIZEOF(t) - _INTSIZEOF(t))
#define _crt_va_start(ap)  (ap = (va_list)0)
)

谈完原理就要谈原理的原理,这段宏定义的预处理就给出了他的运作原理,ap 就相当于 arg, v 就相当于变量 num,va_list 相当于 char *,这里 ADDRESS 相当于取地址,所以就是在对 char 指针强转之后,此时就有了一个指针以一字节为单位,指向入栈的第一个有效元素。要想继续指向后面可变部分,就要继续向下移动四个字节,加上他本身大小就能移动到可变部分。

今天就先到这里,摸了家人们。

以上是关于兰泽又多芳草,可变参数列表的主要内容,如果未能解决你的问题,请参考以下文章

16 可变参数列表和重载问题(最后选择可变参数列表)

C语言 可变参数列表

Java 可变参数列表

jdk5可变参数列表

如何遍历打包的可变参数模板参数列表?

可变参数列表