我希望g ++在vsnprintf中检测下面不正确的隐式转换。 我试着用:
g++ -Wall -Werror -Wconversion -Wformat test.cpp -o test.ext
但没有警告。代码如下:
#include <cstdio>
#include <cstdarg>
void PrintFError ( const char * format, ... )
{
char buffer[256];
va_list args;
va_start (args, format);
vsnprintf (buffer,256,format, args);
perror (buffer);
va_end (args);
}
enum LEVEL
{
INFO = 1,
WRN = 2
};
int main ()
{
PrintFError ("Error opening %s", WRN); // WRN is enum not char*, expecte some compile warning here
return 0;
}
答案 0 :(得分:4)
您必须在函数中添加属性以允许gcc检查:
void PrintFError ( const char * format, ... ) __attribute__ ((format (printf, 1, 2)))
现在最好使用可变参数模板。
之类的东西template <typename ...Ts>
void PrintFError (const char * format, Ts&&...args)
{
char buffer[256];
vsnprintf (buffer, 256, format, std::forward<Ts>(args)...);
perror (buffer);
}
答案 1 :(得分:1)
当您将参数传递给...
而不是printf
内时,此类转化发生在调用网站上。
有关详细信息,请参阅Variadic arguments。
枚举器转换为int
。但是,C ++ 11范围的枚举器不会被隐式转换。
答案 2 :(得分:1)
如果您使用的是GCC或Clang,则可以利用他们的function attributes功能,并宣布您的打印功能
void PrintFError ( const char * format, ...)
__attribute__(format(printf(1,2)));
然后, direct 使用该函数可能会触发警告。
顺便说一句,你也可以自定义你最近的g++
(或gcc
,如果用C编码)编译器,可以使用MELT进行扩展。然后,您可以定义自己的函数属性,并添加自己的检查优化过程。除非你对GCC内部非常熟悉,否则这将需要你至少一周的工作。
最后,在C ++(不在C语言中)中,您可以定义自己的输出operator <<
函数,也许还有一个宏
#define MY_ERROR_AT(Fil,Lin,Out) do { \
std::cerr << Fil << ":" << Lin << ": " << Out << std::endl; } \
while(0)
#define MY_ERROR(Out) MY_ERROR_AT(__FILE__,__LINE__,Out)
和代码MY_ERROR("x=" << x)
稍后在你的程序中。
顺便说一下,你也可以使用C ++ variadic templates,但是你应该使用符合C ++ 11或C ++ 14的编译器(例如g++ -std=c++14
)。