C++ 警告:格式不是字符串文字,也没有格式参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4419293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:21:11  来源:igfitidea点击:

warning: format not a string literal and no format arguments

c++cformatwarningsprintf

提问by Unzi

I want to remove the warning that i get on this line of the code,

我想删除我在这行代码中收到的警告,

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

the thing is when i do this it writes on the file exactly what i want, but if i apply the format %s it doesn't, like this

问题是当我这样做时,它会完全按照我想要的方式写入文件,但是如果我应用格式 %s,则不会,就像这样

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

回答by Sanjit Saluja

This warning is gcc's way of telling you that it cannot verify the format string argument to the printf style function (printf, fprintf... etc). This warning is generated when the compiler can't manually peek into the string and ensure that everything will go as you intend during runtime. Lets look at a couple of examples.

此警告是 gcc 告诉您它无法验证 printf 样式函数(printf、fprintf...等)的格式字符串参数的方式。当编译器无法手动查看字符串并确保在运行时一切按预期进行时,会生成此警告。让我们看几个例子。

Case 1. This string can be verified at compile time and the compiler will allow it without warning:

情况 1. 该字符串可以在编译时验证,编译器将允许它而不发出警告:

printf("This string has no format");
printf("This string has no format");

Case 2: For this case, the compiler can detect that you have a format specifier and will raise a different warning. On my machine it said "warning: too few arguments for format".

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

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

Case 3. Now this is somewhat your case. You are taking a string generated at runtime and trying to print it. The warning you are getting is the compiler warning you that there could be a format specifier in the string. Say for eg "bad%sdata". In this case, the runtime will try to access a non-existent argument to match the %s. Even worse, this could be a user trying to exploit your program (causing it to read data that is not safe to read).

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

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

回答by terminus

While technically there's nothing wrong with calling a printf-like function with a string, it is still bad practice because the string may contain format tokens like %s. If impis %s testfor example, bad things will happen.

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

If you just want to print the impwithout formatting, you should use fputs(imp, fil)(note the reversed arguments).

如果您只想打印imp不带格式的内容,则应使用fputs(imp, fil)(注意颠倒的参数)。

回答by Foad

I think the accepted answerexplained it very well. Basically, as the documentationalso indicates, the compiler can not guarantee that the string variable (in this case imp) is a string literal. You may disable this warning if you are not concerened with safety by puting

我认为接受的答案很好地解释了它。基本上,正如文档所指出的,编译器不能保证字符串变量(在这种情况下imp)是字符串文字。如果您不关心安全,您可以禁用此警告

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

in the header of your code or in the CMake:

在代码的标题或 CMake 中:

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