C 语言的可变参数表函数的设计及原理 - printf(const char* format, ...)

在折腾了一天半以后,终于弄明白为什么自己搜了n多资料,并参照va_list源码写的va_list,va_start,va_arg和va_end 始终无法获得正确参数地址的原因了:因为64位系统与32位系统下,va_list的定义有着根本的不同。通常较为简单的通过地址便宜获取变参的方法是32位环境下的。

如:

32位环境,va_list 被定义为一个指针:

typedef char* va_list;而va_start和va_arg就是简单的根据参数类型进行偏移即可。

64位环境则为结构体:

typedef struct{
unsigned int gp_offset;
unsigned int fp_offset;
char *overflow_arg_area;
char *reg_save_area;
}va_list;
这里的 va_start和va_arg的定义则更为繁琐。其实现在.so的动态库里。

为什么变参设计在32位与64位系统不同,是因为其参数入栈方式的不同:32位系统里,参数自右至左依次入栈(栈底高地址,栈向下增长),那么参数从左至右在栈中的地址依次增大,如果获得了最左的参数地址,可根据类型依次找到后面参数的地址。而64位系统中,调用函数过程中充分使用了寄存器,参数较多时也使用了栈,因此其获取变参的方式便不再是简单的根据类型偏移来获得地址。


关于c语言的变参函数设计详细情况请参照:

(1)32位与64位的不同:http://blog.csdn.net/videosender/article/details/6425671

(2)变参原理及设计原则:http://www.360doc.com/content/07/0423/16/3630_462811.shtml

你可能感兴趣的:(C语言,可变参数函数)