警告:格式不是字符串文字,也不是格式参数

时间:2010-12-11 22:20:52

标签: c++ c format warnings printf

我想删除我在代码的这一行上的警告

FILE *fil;
char *imp;
(...)
fprintf(fil,imp);

事情就是当我这样做时,它在文件上写下了我想要的内容,但如果我应用格式%s则不会,就像这样

fprintf(fil, "%s", imp);

3 个答案:

答案 0 :(得分:50)

这个警告是gcc告诉你它无法验证printf样式函数(printf,fprintf ...等)的格式字符串参数的方法。当编译器无法手动查看字符串并确保在运行时期间所有内容都按预期运行时,将生成此警告。让我们看几个例子。

案例1.可以在编译时验证此字符串,编译器将在不发出警告的情况下允许它:

printf("This string has no format");

案例2:对于这种情况,编译器可以检测到您具有格式说明符并将引发不同的警告。在我的机器上它说“警告:格式的参数太少了。”

// This will most probably crash your machine
printf("Not a safe string to %s"); 

案例3.现在这有点你的情况。您正在运行在运行时生成的字符串并尝试打印它。您收到的警告是编译器警告您字符串中可能有格式说明符。比如说“坏%sdata”。在这种情况下,运行时将尝试访问不存在的参数以匹配%s。更糟糕的是,这可能是用户试图利用您的程序(导致它读取不安全的数据)。

char str[200];
scanf("%s", str)
printf(str)

答案 1 :(得分:17)

虽然从技术上讲,使用字符串调用类似printf的函数没有任何问题,但这仍然是不好的做法,因为该字符串可能包含%s之类的格式标记。例如,如果imp%s test,则会发生不好的事情。

如果您只想打印imp而不进行格式化,则应使用fputs(imp, fil)(请注意反向参数)。

答案 2 :(得分:0)

我认为the accepted answer解释得很好。基本上,正如the documentation也指出的那样,编译器无法保证字符串变量(在这种情况下为imp)是字符串文字。如果您对安全性不满意,则可以禁用此警告

#ifdef _WIN32
#pragma warning (disable : 4774)
#endif

在代码标题或CMake中:

if (CMAKE_C_COMPILER_ID STREQUAL "MSVC")
  set(CMAKE_C_FLAGS "/wd4774") 
endif()