我一直在读到一些编译器支持带有宏的va_list,并且用户能够使用overload the functionality with other macros in order to count the va_list。
对于visual studio,有没有一种方法可以确定va_list是否为空(也就是count==0)?基本上我想知道这个条件:
extern void Foo(const char* psz, ...);
void Test()
{
Foo("My String"); // No params were passed
}
我最初的想法是这样做:
va_list vaStart;
va_list vaEnd;
va_start(vaStart, psz);
va_end(vaEnd);
if (vaStart == vaEnd) ...
问题是va_end只将参数设置为null。
#define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _crt_va_end(ap) ( ap = (va_list)0 )
我在考虑加入一个terminator,但我希望它对调用者隐藏起来,这样就不需要修改现有的代码了。
发布于 2012-07-25 23:42:53
无法知道通过...
传递了多少参数,也无法知道它们是什么类型。变量函数参数只能在您有其他方式(例如printf
-style格式的字符串)来告诉函数期望的情况下才能使用;即使这样,也没有办法验证参数。
C++11提供了类型安全的可变模板。我不知道你的编译器是否支持这些,或者它们是否适合你的问题。
发布于 2017-06-10 09:12:04
我意识到这个问题已经相当陈旧了,但我认为它可能会对我有所帮助。正如Mike Seymour回答的那样,没有绝对可靠的方法来确定va_list
中的参数数量。这就是为什么定义可变函数的传统方法是包含一个包含该信息的参数,例如:void func(const char *str, int count, ...);
,它定义了调用者应该遵守的约定。
EDIT:标准(7.16.1.1.3)实际上对va_arg(vl, type)
返回的值保持沉默,对于超出变量参数列表末尾的任何调用。对于大多数类型,最常见的情况是类型为-零。然而,买者自负--这不是必须的。
当没有更多的参数时,从va_arg(vl, type)
返回的值是类型为零的值。对于数值类型,该值为0。对于指针,它是空指针。对于结构,它是一个所有字段都归零的结构。如果您选择复制va_list
并尝试计算副本,如下所示:
void func(const char *str, ...) {
va_list vl;
va_list vc;
int x;
int count;
count = 0;
va_start(vl, str);
va_copy(vc, vl);
do {
x = va_arg(vc, int);
if (x == 0) break;
count++;
} while (1)
va_end(vc);
.
.
. // do something, or something else,
. // based on the number of args in the list
.
va_end(vl);
您必须假设调用者将遵守约定,不会在列表中传递空值或零值。无论哪种方式,您都必须理解可变函数的调用者有责任遵守所声明的约定。因此,编写您的函数,发布契约,然后轻松入睡。
发布于 2017-12-29 20:36:45
我知道我的答案不是一个“正统”的答案,但是由于va_list宏的限制,我发现以下解决方案是可行的。我们可以将va_list看作一个字符数组,甚至更好,它是一个以null结尾的数组,因此您可以尝试
va_list argptr;
if(strcmp(argptr,""))
{
// not empty
}
else
{
// empty
}
我试过了,它对我很管用。我使用的是Visual Studio 2013旗舰版。项目类型为Win32控制台应用程序。没有编译错误。
https://stackoverflow.com/questions/11653124
复制相似问题