我在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
的用户(不可否认的是,很少和很远)只是不得不吮吸它并接受它?
答案 0 :(得分:3)
(a)=(b)
不可靠。即使传递两个va_list
也是(公共函数将是一个简单的包装器),因为va_list可以是这样的:
typedef __va_list_impl va_list[1];
在其中做一个va_arg会修改另一个(我好像记得Solaris使用这样的东西啊,注册窗口......)。可悲的是,我知道没有办法做你想做的事。