我有一个可变函数:
print_n_integers(7, 1, 2, 3, 4, 5, 6, 7);
int print_n_integers( unsigned int count, ... )
{
// use va_start etc.
}我想使用微软来自sal.h的SAL注释,这样当参数的数量与count不匹配时,Visual Studio编译器就会注意到。我可以通过以下方式将count作为文本强制执行:
int print_n_integers (
_Literal_ unsigned int count,
...
)Visual Studio至少有一些处理printf()的巧妙之处,但是否有一些简单的参数计数?
发布于 2015-06-11 19:22:24
对于您的问题,我想提出一种不使用静态分析的替代方法。
即使您可以获得用于静态分析的可变参数的计数,您仍然必须为每个调用提供正确的计数。您还必须确保所有参数都是整数(或可以提升为整数)。
处理同源类型列表的一种更自然的、非可变的方法是打印一个数组:
void print_nint(const int *arr, size_t n);兼容C99的编译器可以使用compound literals就地创建数组
print_nint((int[]) {0, 8, 15}, 3);此语法适合将其自身包装在宏中:
#define print_int(...) \
print_nint((int[]){__VA_ARGS__}, \
sizeof((int[]) {__VA_ARGS__}) / sizeof(int))此宏执行计数,您可以在不使用显式参数count的情况下使用它:
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);我不提倡不必要地使用宏,但在这种情况下,宏充当模板的角色;它可以减少危险的冗余。
发布于 2015-06-24 04:10:21
不幸的是,SAL中目前还没有针对这种情况的注释。
对printf/scanf/scanf_s函数类的支持被硬编码到分析器中,并分别通过_Printf_format_string_ / _Scanf_format_string_ / _Scanf_s_format_string_注释访问(对于特殊情况,可以使用_Printf_format_string_params_ / _Scanf_format_string_params_ / _Scanf_s_format_string_params_)。因此,您唯一的机会就是游说代码分析团队为您的用例添加支持。
https://stackoverflow.com/questions/30771295
复制相似问题