可变参数相关的宏
首先先了解几个宏:
typedef __gnuc_va_list va_list;
#define va_start(v,l) __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)
这几个宏可以在stdarg.h中找到。va是variable-argument的缩写,方便记忆。
va_list继续追踪为:
typedef __builtin_va_list __gnuc_va_list;
这是由编译器内置的变量,可以和int、char等一样去理解。
va_start(v,l)用于初始化va_list变量(对应参数v),参数l为可变参数前一个参数;
va_arg(v,l)用于获取可变的参数,l对应获取的类型,如int等;
va_end(v)用于结束参数获取。
可变参数获取原理
在函数的调用时,参数压栈是从右到左进行的,即最后一个参数先入栈,第一个参数最后入栈。栈的生长方向一般都是向下生长的,即先入栈的地址高,后入栈的地址低。
地址低 |———————————————|
| 全局量 |
堆起始->|———————————————|
| 堆向高地址增长 |
| |
| |
| 自由空间 |
| |
| |
| 栈向低地址增长 |
地址高 栈起始->|———————————————|
当我们知道第一个参数(即最后一个入栈的参数)的地址,同时知道各个参数的类型时,即可通过地址的移动获取到对一个的变量值。
地址低 |---------------|
...... |----<