测试代码
#include <stdarg.h>
#include <stdio.h>
void s(const char* str1, const char* str2, ...)
{
va_list va_list_;
va_start(va_list_, str1);
const char* p1 = va_arg(va_list_, const char*);
printf("p1 : [%p] [%s]\n", p1, p1);
const char* p2 = va_arg(va_list_, const char*);
printf("p2 : [%p] [%s]\n", p2, p2);
const char* p3 = va_arg(va_list_, const char*);
printf("p3 : [%p] [%s]\n", p3, p3);
const char* p4 = va_arg(va_list_, const char*);
printf("p4 : [%p] [%s]\n", p4, p4);
const char* p5 = va_arg(va_list_, const char*);
printf("p5 : [%p] [%s]\n", p5, p5);
const char* p6 = va_arg(va_list_, const char*);
printf("p6 : [%p] [%s]\n", p6, p6);
//const char* p7 = va_arg(va_list_, const char*);
//printf("p7 : [%p] [%s]\n", p7, p7);
//const char* p8 = va_arg(va_list_, const char*);
//printf("p8 : [%p] [%s]\n", p8, p8);
//const char* p9 = va_arg(va_list_, const char*);
//printf("p9 : [%p] [%s]\n", p9, p9);
//const char* p10 = va_arg(va_list_, const char*);
//printf("p10 : [%p] [%s]\n", p10, p10);
va_end(va_list_);
}
int main()
{
s("11", "22", "33", "44", "55");
return 0;
}
windows下运行打印结果
p1 : [00076BA4] [22]
p2 : [00076BA0] [33]
p3 : [00076B9C] [44]
p4 : [00076B98] [55]
p5 : [0007104B] [闋]
p6 : [0007104B] [闋]
可以看到,如果使用str1作为va_start的参数,那么第一次调用va_arg返回的指针,指向的是str2。多次调用va_arg后,返回的指针的地址间隔为4,并且是从高地址向低地址排列,依此指向所传递的字符串。
p1 : [00BA6B68] [33]
p2 : [00BA6B54] [44]
p3 : [00BA6B40] [55]
p4 : [00BA104B] [闋]
p5 : [00BA104B] [闋]
p6 : [0060A000] []
如果使用str2作为va_start的参数,那么第一次调用va_arg返回的指针,指向的是“33”。多次调用va_arg后,返回的指针的地址间隔是20
linux下运行打印结果(为了研究指针偏移量更改了字符串字符数)
p1 : [0x400ba3] [33333333]
p2 : [0x400b9a] [44444444]
p3 : [0x400b91] [55555555]
p4 : [(nil)] [(null)]
p5 : [(nil)] [(null)]
p6 : [0x7f332ccb7555] [����w]
相同点
va_arg执行多次后,windows与linux下程序都会崩溃。
va_arg返回的指针的地址都是从高向低排列。
不同点
va_start的第二个参数。
windows,va_start通过第二个参数指定起始的字符串后,后面调用va_arg时是获取到的下一个参数。
linux,va_start通过第二个参数指定起始的字符串后,后面调用va_arg时获取到的参数跟va_start里面指定的无关,获取到的一定是...表示的参数里的第一个参数。
va_arg返回的指针的偏移
windows,指针的偏移是固定的,这个是操作系统决定的。
linux,指针的偏移是跟传递的字符串参数相关的,偏移的大小是字符串字符数+1。
va_arg遍历参数结束时返回的指针
windows,遍历可变参数表结束后返回的头两个指针不是空,但地址相同。
linux,遍历可变参数表结束后返回的头两个指针都是空。