c里面的变长参数,c++里面也有。提供了:
一个类型
va_list
3个宏
va_start
va_arg
va_end
使用的例子是这样的
int foo(char* fmt, ...){
va_list args;
va_start(args, fmt);
int i = va_arg(args, int);
double f = va_arg(args, double);
va_end(args);
}
使用还是很方便的,但是实现是怎么样的呢? 要讲实现,先得讲讲c里面的函数调用约定。
在x86下,c语言多多种调用约定,而支持变长参数的只有__cdecl。 参数是放在栈上的,调用者负责调整栈.
所以,参数实际上是从第一个到最后一个从低到高排列在栈上的,实现的方法就是
va_list是一个char*.让va_list指向最后一个不是变长参数的参数的后面,也就是第一个变长参数.
va_arg就是按照类型取值,并且把指针往后移动sizeof(type)就行了。
但是到了x64上,就没这么简单了。x64上不论是vc还是gcc都只有一种类似fastcall的调用约定。参数首先是放在寄存器里,不够了再往栈上放。这样一来,参数就不是在栈的内存上连续排列了。变长参数的实现就需要多做点事了。
先讲比较简单的一种,VC的处理方式
vc的调用约定[1] 是,前4个参数,如果是整数,指针或者其他1