如何确定va_list是否为空
How to determine if va_list is empty
我读到一些编译器支持带有宏的va_list,用户可以用其他宏重载该功能以计算va_list。
有了visualstudio,有没有办法确定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只将param设置为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 )
我在考虑加入一个终止符,但我希望它对调用者隐藏起来,这样现有的代码就不需要更改了。
无法判断有多少参数通过...
,也无法判断它们是什么类型。只有当您有其他方式(例如printf
风格的格式字符串)来告诉函数期望什么时,才能使用变分函数参数;即便如此,也无法验证这些论点。
C++11提供了类型安全的可变模板。我不知道你的编译器是否支持这些,或者它们是否适合你的问题。
我意识到这个问题已经很老了,但我认为稍微充实一下可能会有所帮助。正如Mike Seymour非常正确地回答的那样,没有绝对可靠的方法来确定va_list
中的自变量数量。这就是为什么定义可变函数的传统方法是包括一个具有该信息的参数,比如:void func(const char *str, int count, ...);
,它定义了调用者应该遵守的合同
EDIT:对于变量参数列表末尾之后的任何调用,标准(7.16.1.1.3)实际上对va_arg(vl, type)
返回的值保持沉默。大多数类型最常见的情况是类型为零。然而,CAVEAT EMPTOR——它不一定是。
当不再有参数时,从va_arg(vl, type)
返回的值是类型化的零值。对于数字类型,它是0。对于指针,它是一个NULL指针。对于structs,它是一个所有字段都为零的structs。如果您选择复制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);
您必须假设调用者将遵守约定,不会在列表中传递NULL或零值。无论哪种方式,您都必须理解variadic函数的调用者有责任遵守所声明的契约。所以,编写你的函数,发布契约,然后睡个安稳觉。
我知道我的答案不是"正统"答案,但由于va_list宏的限制,我找到了以下解决方案。我们可以将va_list看作是一个字符数组,更好的是,它是一个以null结尾的字符数组,因此您可以尝试
va_list argptr;
if(strcmp(argptr,""))
{
// not empty
}
else
{
// empty
}
我试过了,对我有效。我使用了Visual Studio 2013 Ultimate。项目类型为Win32控制台应用程序。没有编译错误。
- '[](std::list& list)<int>{return std::move(list)}(list)' 是否保证将 'list' 留空?
- "std::list::splice(std::const_iterator pos, std::list&& other)"是否保证将"其他"留空?
- 使用容器中元素的别名删除带有 std::list::remove 的元素是否正确?
- std::list 模板是否需要其实例类型中的复制构造函数(或等效项)?
- 是否可以<char> <int> 在 C++ 中将 std::list 转换为 std::list
- boost::instrusive::list 带有自动取消链接钩子:我可以使用列表中的值来确定列表是否只有一个元素
- thread_local std::list 是否会在呼叫清除时放弃分配的内存
- 如何使用QFtp::list和QFtp::listInfo来检查目录是否存在
- 在修改列表后,std :: list&lt; t&gt; :: end()的值是否会更改
- C++ std::list<T>::迭代器 迭代器是否具有<T>对成员函数的访问?
- 对于 std::list 是否有等价的 vector::reserve() ?
- std::string::clear和std::list::clear是否从内存中擦除数据
- 是否可以保存std::list中新插入元素的迭代器,然后使用该迭代器安全地擦除该元素?
- 是否有库来解析FTP LIST命令的输出
- std::list是否保证项永远不会被移动到不同的内存位置?
- "std::map with mutexes"与并行插入、查找、擦除之间是否有任何速度测试"libcds maps (Michael Hashmap and Split Order List)"?
- std::list的pop_back()是否取消内存分配?
- 在c++中,enum [tag] [: type] {enum-list} [declarator]是否合法?
- 有效地检查数字在List<List中是否仅作为正数或取反存在<int>>
- std::list 的擦除成员函数是否为所有存储的元素调用析构函数?