C varargs - va_copy问题

时间:2009-08-11 09:24:20

标签: c variadic-functions

我在C中编写了一个带有可变数量参数的函数。

size_t myprintf(char *fmt, ...);

到目前为止,这么好。我决定最好用Right Way™做一些事情并制作一个带有可变参数的版本,另一个版本带有va_list

size_t myprintf(char *fmt, ...);
size_t myvprintf(char *fmt, va_list args);

没那么难。除了my_vprintf()需要将其args发送到两个不同的函数(首先发送到snprintf(),长度为0以确定我们需要多少空间,然后再发送到sprintf()分配了那么多空间。我使用va_copy执行此操作。

size_t myvprintf(char *fmt, va_list args)
{
    va_list args2;
    va_copy(args, args2);
    // do stuff with args2
    va_end(args2);
    // do more stuff with args
}

这一切都很好,花花公子,但C99实施得有点差。我希望,如果可能的话,我的代码也可以在C89中工作,并且可以与尽可能多的编译器和尽可能多的平台一起工作。我目前在#include <stddef.h>之后但在任何代码之前有这个:

#ifndef va_copy
# ifdef __va_copy
#  define va_copy(a,b) __va_copy(a,b)
# else /* !__va_copy */
#  define va_copy(a,b) ((a)=(b))
# endif /* __va_copy */
#endif /* va_copy */

我被认为((a)=(b))是不可靠的,我应该使用memcpy()或类似的东西,但这仍然是“如果你不支持C99,我希望它的工作“而不是”如果你不支持C99,永远不要害怕“(这就是我想要的)。有没有什么好方法可以解决这个限制?我已经看到了一些解决方案 - va_list函数吃了一个参数并递归,传递va_list两次以便制作两个单独的副本等等 - 但我不知道它们会有多好工作(如果我只想打电话给vsnprintf(),那么递归解决方案不会那么好,现在,是吗?)。

所以我转向你,StackOverflow用户。我还能做些什么来提供C89兼容性,或者是没有va_copy__va_copy的用户(不可否认的是,很少和很远)只是不得不吮吸它并接受它?

1 个答案:

答案 0 :(得分:3)

(a)=(b)不可靠。即使传递两个va_list也是(公共函数将是一个简单的包装器),因为va_list可以是这样的:

typedef __va_list_impl va_list[1];

在其中做一个va_arg会修改另一个(我好像记得Solaris使用这样的东西啊,注册窗口......)。可悲的是,我知道没有办法做你想做的事。