C++ 如何通过GCC检测vsnprintf中的隐式转换

C++ 如何通过GCC检测vsnprintf中的隐式转换,c++,gcc,g++,printf,C++,Gcc,G++,Printf,我希望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;

我希望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;
}
#包括
#包括
void PrintFError(常量字符*格式,…)
{
字符缓冲区[256];
va_列表参数;
va_开始(参数,格式);
vsnprintf(缓冲区,256,格式,参数);
缓冲区;
va_端(args);
}
枚举级别
{
INFO=1,
WRN=2
};
int main()
{
PrintFError(“打开%s时出错”,WRN);//WRN是枚举而不是字符*,此处需要一些编译警告
返回0;
}

当您将参数传递给
,而不是在
printf
内部时,这种类型的转换在调用站点发生

有关更多详细信息,请参阅


枚举数转换为
int
。但是,C++11作用域枚举数不会隐式转换。

您必须向函数添加属性以允许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);
}
模板
void PrintFError(常量字符*格式,Ts&…args)
{
字符缓冲区[256];
vsnprintf(缓冲区,256,格式,标准::转发(args)…);
缓冲区;
}
如果您正在使用或,您可以利用它们的功能,将您的打印功能声明为

void PrintFError ( const char * format, ...) 
   __attribute__(format(printf(1,2)));
之后直接使用该函数可能会触发警告

顺便说一句,您还可以通过使用扩展来定制最近的
g++
(或者
gcc
,如果是用C编写的)编译器。然后,您可以定义自己的函数属性,并添加自己的检查优化过程。这将花费你至少一周的时间,除非你非常熟悉GCC的内部结构


<>最后,在C++(不在C)中,可以定义自己的输出<代码>运算符是的,C++ 11强枚举类型是枚举类型的一种解决方案。但替换遗留代码是一项巨大的工作。我希望在实用程序函数(日志打印)中找到一些常用方法
 #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)