请查看我的小型C / C ++程序。
// va_nest.c
#include <stdarg.h>
#include <stdio.h>
void nest2(const char *fmt, ...)
{
va_list args2, args_dig;
int *pi, i;
va_start(args2, fmt);
args_dig = va_arg(args2, va_list);
// !!! try to fetch the nested va_list object.
pi = va_arg(args_dig, int*);
i = va_arg(args_dig, int);
printf("Inner: @%p , %d\n", pi, i);
va_end(args2);
}
void nest1(const char *fmt, ...)
{
va_list args1;
va_start(args1, fmt);
nest2(fmt, args1);
va_end(args1);
}
int main()
{
int var = 11;
printf("Outer: @%p , %d\n", &var, var);
nest1("abc", &var, var);
return 0;
}
在openSUSE 13.1 x86上,它输出的只是我想要的(无论使用gcc还是g ++),
Outer: @0xbfa18d8c , 11
Inner: @0xbfa18d8c , 11
但是,它在openSUSE 13.1 x64机器上使用x86_64编译器失败。
如果我用gcc
编译它,它编译好,但输出是意外的。
$ gcc -o vac va_nest.c
$ ./vac
Outer: @0x7fffb20f766c , 11
Inner: @0x1b01000000636261 , 4209411
如果我用g++
编译它,它甚至无法编译。
$ g++ -o vacpp va_nest.c
va_nest.c: In function ‘void nest2(const char*, ...)’:
va_nest.c:12:11: error: invalid array assignment
args_dig = va_arg(args2, va_list);
^
gcc和g ++版本是4.8.1
有人可以帮我吗?我希望在x64上获得与Linux x86编译器相同的结果。
答案 0 :(得分:4)
请勿尝试使用va_list
聪明。相反,使用这样的代码:
nest2(fmt, args1);
(即确保所有函数使用隐藏在va_list
后面的相同结构)。然后你可以像这样定义第二个函数:
void nest2(const char *fmt, va_list args1)
同时确保您完全致电va_end()
。嵌套将无法可靠地工作(即如果它有效,那就比其他任何东西更幸运了。)
如有疑问,请查看GLIBC的源代码,尤其是fprintf.c和vfprintf.c。
int
__fprintf (FILE *stream, const char *format, ...)
{
va_list arg;
int done;
va_start (arg, format);
done = vfprintf (stream, format, arg);
va_end (arg);
return done;
}
以后:
int
vfprintf (FILE *s, const CHAR_T *format, va_list ap)
{
答案 1 :(得分:1)
我意识到传递va_list对象的地址(而不是对象本身)是可行的,在linux gcc和MSVC 2008(32位和64位编译器)上验证。
// va_nesta.c
#include <stdarg.h>
#include <stdio.h>
#include <assert.h>
void nest2(const char *fmt, ...)
{
va_list args2, *args_dig;
int *pi, i;
va_start(args2, fmt);
args_dig = va_arg(args2, va_list*);
// !!! ★ try to fetch the nested va_list object's address.
pi = va_arg(*args_dig, int*);
i = va_arg(*args_dig, int);
printf("Inner: @%p , %d\n", pi, i);
va_end(args2);
}
void nest1(const char *fmt, ...)
{
va_list args1;
va_start(args1, fmt);
nest2(fmt, &args1); // ★use va_list object's address!
va_end(args1);
}
int main()
{
int var = 11;
printf("Outer: @%p , %d\n", &var, var);
nest1("abc", &var, var);
return 0;
}