我想提出一种不使用静态分析的替代方法来解决您的问题。
即使您可以获得静态分析的可变参数的计数,您仍然必须为每个调用提供正确的计数。您还必须确保所有参数都是(或可以提升为)整数。
处理同质类型列表的更自然、非可变的方法是打印一个数组:
void print_nint(const int *arr, size_t n);
C99 兼容的编译器可以使用复合文字在现场创建数组:
print_nint((int[]) {0, 8, 15}, 3);
这种语法适合自己包装在一个宏中:
#define print_int(...) \
print_nint((int[]){__VA_ARGS__}, \
sizeof((int[]) {__VA_ARGS__}) / sizeof(int))
此宏进行计数,您可以在没有显式参数计数的情况下使用它:
print_int(1, 2, 3.0, rand(), i++, j++);
可变参数的第二个扩展在内部使用sizeof
而不是评估。在上面的行中,rand()
只调用一次并且i
只j
增加一次。浮点参数int
在打印之前转换为。
Visual Studio 在2013 RC中引入了复合文字,但旧版本不支持它们。不幸的是,复合文字也会使您的代码无法用于 C++ 编译器。对于这些情况,您可以修改宏来定义一个临时数组:
#define print_int(...) { \
int PrintMe_[] = {__VA_ARGS__}; \
print_nint(PrintMe_, sizeof(PrintMe_) / sizeof(*PrintMe_)); \
}
但是,只有在 void 上下文中调用该函数时,此策略才有效。
如果只使用宏,则数组及其大小是一致的。但是您可以发布底层实现并使用 SAL 对其进行注释:
void print_nint(_In_reads_(n) const int *arr, size_t n);
我不提倡无缘无故地使用宏,但在这种情况下,宏起到了模板的作用;它可以减少危险的冗余。