C语言 如何禁用几行代码的 GCC 警告
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3378560/
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
How to disable GCC warnings for a few lines of code
提问by Matt Joiner
In Visual C++, it's possible to use #pragma warning (disable: ...). Also I found that in GCC you can override per file compiler flags. How can I do this for "next line", or with push/pop semantics around areas of code using GCC?
在 Visual C++ 中,可以使用#pragma warning (disable: ...). 我还发现在 GCC 中,您可以覆盖每个文件的编译器标志。我如何为“下一行”或使用 GCC 的代码区域周围的推送/弹出语义执行此操作?
回答by Matt Joiner
It appears this can be done. I'm unable to determine the version of GCC that it was added, but it was sometime before June 2010.
看来这是可以做到的。我无法确定它添加的 GCC 版本,但它是在 2010 年 6 月之前的某个时间。
Here's an example:
下面是一个例子:
#pragma GCC diagnostic error "-Wuninitialized"
foo(a); /* error is given for this one */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized"
foo(b); /* no diagnostic for this one */
#pragma GCC diagnostic pop
foo(c); /* error is given for this one */
#pragma GCC diagnostic pop
foo(d); /* depends on command line options */
回答by Ian Pilcher
To net everything out, this is an example of temporarilydisabling a warning:
为了解决所有问题,这是一个暂时禁用警告的示例:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
write(foo, bar, baz);
#pragma GCC diagnostic pop
You can check the GCC documentation on diagnostic pragmasfor more details.
回答by Christian Hujer
TL;DR: If it works, avoid, or use specifiers like __attribute__, otherwise _Pragma.
TL;DR:如果有效,请避免或使用诸如__attribute__, 之类的说明符,否则_Pragma。
This is a short version of my blog article Suppressing Warnings in GCC and Clang.
这是我的博客文章Suppressing Warnings in GCC 和 Clang的简短版本 。
Consider the following Makefile
考虑以下 Makefile
CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror
.PHONY: all
all: puts
for building the following puts.csource code
用于构建以下puts.c源代码
#include <stdio.h>
int main(int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
It will not compile because argcis unused, and the settings are hardcore (-W -Wall -pedantic -Werror).
它不会编译,因为argc未使用,并且设置是核心 ( -W -Wall -pedantic -Werror)。
There are 5 things you could do:
你可以做5件事:
- Improve the source code, if possible
- Use a declaration specifier, like
__attribute__ - Use
_Pragma - Use
#pragma - Use a command line option.
- 如果可能,改进源代码
- 使用声明说明符,例如
__attribute__ - 用
_Pragma - 用
#pragma - 使用命令行选项。
Improving the source
改善源头
The first attempt should be checking if the source code can be improved to get rid of the warning. In this case we don't want to change the algorithm just because of that, as argcis redundant with !*argv(NULLafter last element).
第一次尝试应该是检查源代码是否可以改进以消除警告。在这种情况下,我们不想仅仅因为这个而改变算法,因为(在最后一个元素之后)argc是多余的。!*argvNULL
Using a declaration specifier, like __attribute__
使用声明说明符,例如 __attribute__
#include <stdio.h>
int main(__attribute__((unused)) int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
If you're lucky, the standard provides a specifier for your situation, like _Noreturn.
如果幸运的话,该标准会为您的情况提供一个说明符,例如_Noreturn.
__attribute__is proprietary GCC extension (supported by Clang and some other compilers like armccas well) and will not be understood by many other compilers. Put __attribute__((unused))inside a macro if you want portable code.
__attribute__是专有的 GCC 扩展(由 Clang 和其他一些编译器支持armcc)并且不会被许多其他编译器理解。__attribute__((unused))如果您想要可移植的代码,请将其放入宏中。
_Pragmaoperator
_Pragma操作员
_Pragmacan be used as an alternative to #pragma.
_Pragma可以作为替代品使用#pragma。
#include <stdio.h>
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wunused-parameter\"")
int main(int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
_Pragma("GCC diagnostic pop")
The main advantage of the _Pragmaoperator is that you could put it inside macros, which is not possible with the #pragmadirective.
_Pragma操作符的主要优点是你可以把它放在宏中,而这在#pragma指令中是不可能的。
Downside: It's almost a tactical nuke, as it works line-based instead of declaration-based.
缺点:它几乎是一个战术核武器,因为它基于行而不是基于声明的工作。
The _Pragmaoperator was introduced in C99.
该_Pragma运算符是在 C99 中引入的。
#pragmadirective.
#pragma指示。
We could change the source code to suppress the warning for a region of code, typically an entire function:
我们可以更改源代码以抑制一段代码区域的警告,通常是整个函数:
#include <stdio.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
int main(int argc, const char *argv[])
{
while (*++argc) puts(*argv);
return 0;
}
#pragma GCC diagnostic pop
Downside: It's almost a tactical nuke, as it works line-based instead of declaration-based.
缺点:它几乎是一个战术核武器,因为它基于行而不是基于声明的工作。
Note that a similar syntax exists in clang.
请注意,clang 中存在类似的语法。
Suppressing the warning on the command line for a single file
抑制单个文件在命令行上的警告
We could add the following line to the Makefileto suppress the warning specifically for puts:
我们可以将以下行添加到Makefile以抑制专门针对看跌期权的警告:
CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror
.PHONY: all
all: puts
puts.o: CPPFLAGS+=-Wno-unused-parameter
This is probably not want you want in your particular case, but it may help other reads who are in similar situations.
在您的特定情况下,这可能不是您想要的,但它可能有助于处于类似情况的其他阅读。
回答by Martin Gerhardy
#define DIAG_STR(s) #s
#define DIAG_JOINSTR(x,y) DIAG_STR(x ## y)
#ifdef _MSC_VER
#define DIAG_DO_PRAGMA(x) __pragma (#x)
#define DIAG_PRAGMA(compiler,x) DIAG_DO_PRAGMA(warning(x))
#else
#define DIAG_DO_PRAGMA(x) _Pragma (#x)
#define DIAG_PRAGMA(compiler,x) DIAG_DO_PRAGMA(compiler diagnostic x)
#endif
#if defined(__clang__)
# define DISABLE_WARNING(gcc_unused,clang_option,msvc_unused) DIAG_PRAGMA(clang,push) DIAG_PRAGMA(clang,ignored DIAG_JOINSTR(-W,clang_option))
# define ENABLE_WARNING(gcc_unused,clang_option,msvc_unused) DIAG_PRAGMA(clang,pop)
#elif defined(_MSC_VER)
# define DISABLE_WARNING(gcc_unused,clang_unused,msvc_errorcode) DIAG_PRAGMA(msvc,push) DIAG_DO_PRAGMA(warning(disable:##msvc_errorcode))
# define ENABLE_WARNING(gcc_unused,clang_unused,msvc_errorcode) DIAG_PRAGMA(msvc,pop)
#elif defined(__GNUC__)
#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
# define DISABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,push) DIAG_PRAGMA(GCC,ignored DIAG_JOINSTR(-W,gcc_option))
# define ENABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,pop)
#else
# define DISABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,ignored DIAG_JOINSTR(-W,gcc_option))
# define ENABLE_WARNING(gcc_option,clang_option,msvc_unused) DIAG_PRAGMA(GCC,warning DIAG_JOINSTR(-W,gcc_option))
#endif
#endif
This should do the trick for gcc, clang and msvc
这应该对 gcc、clang 和 msvc 有用
Can be called with e.g.:
可以用例如调用:
DISABLE_WARNING(unused-variable,unused-variable,42)
[.... some code with warnings in here ....]
ENABLE_WARNING(unused-variable,unused-variable,42)
see https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html, http://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmasand https://msdn.microsoft.com/de-DE/library/d9x1s805.aspxfor more details
看到https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html,http://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas和https://msdn.microsoft .com/de-DE/library/d9x1s805.aspx了解更多详情
You need at least version 4.02 to use these kind of pragmas for gcc, not sure about msvc and clang about the versions.
您至少需要 4.02 版才能将这些编译指示用于 gcc,不确定 msvc 和 clang 的版本。
It looks like the push pop pragma handling for gcc is a little bit broken. If you enable the warning again, you still get the warning for the block that was inside the DISABLE_WARNING/ENABLE_WARNING block. For some versions of gcc it works, for some it doesn't.
看起来 gcc 的 push pop pragma 处理有点坏。如果再次启用警告,您仍然会收到 DISABLE_WARNING/ENABLE_WARNING 块内的块的警告。对于某些版本的 gcc 它有效,对于某些版本则无效。
回答by Joe D
#pragma GCC diagnostic ignored "-Wformat"
Replace "-Wformat" with the name of your warning flag.
将“-Wformat”替换为警告标志的名称。
AFAIK there is no way to use push/pop semantics for this option.
AFAIK 无法为此选项使用推送/弹出语义。
回答by Shital Shah
I had same issue with external libraries like ROS headers. I like to use following options in CMakeLists.txt for stricter compilation:
我对像 ROS 头文件这样的外部库有同样的问题。我喜欢在 CMakeLists.txt 中使用以下选项来进行更严格的编译:
set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -Wextra -Wstrict-aliasing -pedantic -Werror -Wunreachable-code ${CMAKE_CXX_FLAGS}")
However doing this causes all kind of pedantic errors in externally included libraries as well. The solution is to disable all pedantic warnings before you include external libraries and re-enable like this:
然而,这样做也会导致外部包含的库中出现各种迂腐的错误。解决方案是在包含外部库并重新启用之前禁用所有迂腐警告,如下所示:
//save compiler switches
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
//Bad headers with problem goes here
#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>
//restore compiler switches
#pragma GCC diagnostic pop
回答by nemequ
I know the question is about GCC, but for people looking for how to do this in other and/or multiple compilers…
我知道这个问题是关于 GCC 的,但是对于那些在其他和/或多个编译器中寻找如何做到这一点的人......
TL;DR
TL; 博士
You might want to take a look at Hedley, which is a public-domain single C/C++ header I wrote which does a lotof this stuff for you. I'll put a quick section about how to use Hedley for all this at the end of this post.
您可能想看看Hedley,它是我编写的公共域单个 C/C++ 头文件,它为您做了很多这样的事情。我将在这篇文章的末尾快速介绍如何使用 Hedley 完成所有这些工作。
Disabling the warning
禁用警告
#pragma warning (disable: …)has equivalents in most compilers:
#pragma warning (disable: …)在大多数编译器中都有等价物:
- MSVC:
#pragma warning(disable:4996) - GCC:
#pragma GCC diagnostic ignored "-W…"where the ellipsis is the name of the warning; e.g.,#pragma GCC diagnostic ignored "-Wdeprecated-declarations. - clang:
#pragma clang diagnostic ignored "-W…". The syntax is basically the same as GCC's, and many of the warning names are the same (though many aren't). - Intel C Compiler: Use the MSVC syntax, but keep in mind that warning numbers are totally different. Example:
#pragma warning(disable:1478 1786). - PGI: There is a
diag_suppresspragma:#pragma diag_suppress 1215,1444 - TI: There is a
diag_suppresspragma with the same syntax (but different warning numbers!) as PGI:pragma diag_suppress 1291,1718 - Oracle Developer Studio (suncc): there is an
error_messagespragma. Annoyingly, the warnings are different for the C and C++ compilers. Both of these disable basically the same warnings:- C:
#pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS) - C++:
#pragma error_messages(off,symdeprecated,symdeprecated2)
- C:
- IAR: also uses
diag_suppresslike PGI and TI, but the syntax is different. Some of the warning numbers are the same, but I others have diverged:#pragma diag_suppress=Pe1444,Pe1215 - Pelles C: similar to MSVC, though again the numbers are different
#pragma warn(disable:2241)
- MSVC:
#pragma warning(disable:4996) - GCC:
#pragma GCC diagnostic ignored "-W…"省略号是警告的名称;例如,#pragma GCC diagnostic ignored "-Wdeprecated-declarations。 - 叮当:
#pragma clang diagnostic ignored "-W…"。语法与 GCC 基本相同,许多警告名称相同(尽管许多不同)。 - 英特尔 C 编译器:使用 MSVC 语法,但请记住,警告编号完全不同。例子:
#pragma warning(disable:1478 1786)。 - PGI:有一个
diag_suppress编译指示:#pragma diag_suppress 1215,1444 - TI:有一个
diag_suppresspragma 语法与 PGI 相同(但警告编号不同!):pragma diag_suppress 1291,1718 - Oracle Developer Studio (suncc):有一个
error_messagespragma。令人讨厌的是,C 和 C++ 编译器的警告是不同的。这两个都禁用了基本相同的警告:- C:
#pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS) - C++:
#pragma error_messages(off,symdeprecated,symdeprecated2)
- C:
- IAR:也
diag_suppress像 PGI 和 TI 一样使用,但语法不同。一些警告数字是相同的,但我其他人有分歧:#pragma diag_suppress=Pe1444,Pe1215 - Pelles C:与 MSVC 相似,但数字又不同
#pragma warn(disable:2241)
For most compilers it is often a good idea to check the compiler version before trying to disable it, otherwise you'll just end up triggering another warning. For example, GCC 7 added support for the -Wimplicit-fallthroughwarning, so if you care about GCC before 7 you should do something like
对于大多数编译器来说,在尝试禁用之前检查编译器版本通常是个好主意,否则你最终只会触发另一个警告。例如,GCC 7 添加了对-Wimplicit-fallthrough警告的支持,因此如果您在 7 之前关心 GCC,您应该执行类似的操作
#if defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
For clang and compilers based on clang such as newer versions of XL C/C++ and armclang, you can check to see if the compiler knows about a particular warning using the __has_warning()macro.
对于 clang 和基于 clang 的编译器(例如 XL C/C++ 和 armclang 的较新版本),您可以使用__has_warning()宏检查编译器是否知道特定警告。
#if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
Of course you also have to check to see if the __has_warning()macro exists:
当然,您还必须检查__has_warning()宏是否存在:
#if defined(__has_warning)
# if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
# endif
#endif
You may be tempted to do something like
你可能会想做类似的事情
#if !defined(__has_warning)
# define __has_warning(warning)
#endif
So you can use __has_warninga bit more easily. Clang even suggests something similar for the __has_builtin()macro in their manual. Do not do this. Other code may check for __has_warningand fall back on checking compiler versions if it doesn't exist, and if you define __has_warningyou'll break their code. The right way to do this is to create a macro in your namespace. For example:
所以你可以__has_warning更轻松地使用。Clang 甚至__has_builtin()在他们的手册中为宏提出了类似的建议。 不要这样做。__has_warning如果编译器版本不存在,其他代码可能会检查并回退到检查编译器版本,如果你定义__has_warning你会破坏他们的代码。正确的方法是在您的命名空间中创建一个宏。例如:
#if defined(__has_warning)
# define MY_HAS_WARNING(warning) __has_warning(warning)
#else
# define MY_HAS_WARNING(warning) (0)
#endif
Then you can do stuff like
然后你可以做类似的事情
#if MY_HAS_WARNING(warning)
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#elif defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
Pushing and popping
推动和弹出
Many compilers also support a way to push and pop warnings onto a stack. For example, this will disable a warning on GCC for one line of code, then return it to its previous state:
许多编译器还支持将警告推入和弹出堆栈的方法。例如,这将在 GCC 上为一行代码禁用警告,然后将其返回到以前的状态:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop
Of course there isn't a lot of agreement across compilers about the syntax:
当然,编译器之间关于语法的共识并不多:
- GCC 4.6+:
#pragma GCC diagnostic push/#pragma GCC diagnostic pop - clang:
#pragma clang diagnostic push/#pragma diagnostic pop - Intel 13+ (and probably earlier):
#pragma warning(push)/#pragma warning(pop) - MSVC 15+ (VS 9.0 / 2008):
#pragma warning(push)/#pragma warning(pop) - ARM 5.6+:
#pragma push/#pragma pop - TI 8.1+:
#pragma diag_push/#pragma diag_pop - Pelles C 2.90+ (and probably earlier):
#pragma warning(push)/#pragma warning(pop)
- 海湾合作委员会 4.6+:
#pragma GCC diagnostic push/#pragma GCC diagnostic pop - 叮当:
#pragma clang diagnostic push/#pragma diagnostic pop - 英特尔 13+(可能更早):
#pragma warning(push)/#pragma warning(pop) - MSVC 15+ (VS 9.0 / 2008):
#pragma warning(push)/#pragma warning(pop) - ARM 5.6+:
#pragma push/#pragma pop - TI 8.1+:
#pragma diag_push/#pragma diag_pop - Pelles C 2.90+(可能更早):
#pragma warning(push)/#pragma warning(pop)
If memory serves, for some very old versions of GCC (like 3.x, IIRC) the push/pop pragmas had to be outsideof the function.
如果没记错的话,对于一些非常旧的 GCC 版本(如 3.x、IIRC),push/pop 编译指示必须在函数之外。
Hiding the gory details
隐藏血腥细节
For most compilers it's possible to hide the logic behind macros using _Pragma, which was introduced in C99. Even in non-C99 mode, most compilers support _Pragma; the big exception is MSVC, which has its own __pragmakeyword with a different syntax. The standard _Pragmatakes a string, Microsoft's version doesn't:
对于大多数编译器,可以使用_PragmaC99 中引入的来隐藏宏背后的逻辑。即使在非 C99 模式下,大多数编译器也支持_Pragma; 最大的例外是 MSVC,它有自己的__pragma关键字和不同的语法。标准_Pragma需要一个字符串,微软的版本没有:
#if defined(_MSC_VER)
# define PRAGMA_FOO __pragma(foo)
#else
# define PRAGMA_FOO _Pragma("foo")
#endif
PRAGMA_FOO
Is roughly equivalent, once preprocessed, to
大致相当于,一旦预处理,
#pragma foo
This lets us create macros so we can write code like
这让我们可以创建宏,以便我们可以编写如下代码
MY_DIAGNOSTIC_PUSH
MY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated_function();
MY_DIAGNOSTIC_POP
And hide away all the ugly version checks in the macro definitions.
并隐藏宏定义中所有丑陋的版本检查。
The easy way: Hedley
简单的方法:赫德利
Now that you understand the mechanics of how to do stuff like this portably while keeping your code clean, you understand what one of my projects, Hedleydoes. Instead of digging through tons of documentation and/or installing as many versions of as many compilers as you can to test with, you can just include Hedley (it is a single public domain C/C++ header) and be done with it. For example:
既然您了解了如何在保持代码整洁的同时可移植地执行此类操作的机制,您就会了解我的一个项目Hedley所做的事情。无需深入研究大量文档和/或安装尽可能多的编译器版本以进行测试,您只需包含 Hedley(它是一个公共域 C/C++ 头文件)并完成它。例如:
#include "hedley.h"
HEDLEY_DIAGNOSTIC_PUSH
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP
Will disable the warning about calling a deprecated function on GCC, clang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles, and possibly others (I probably won't bother updating this answer as I update Hedley). And, on compilers which aren't known to work, the macros will be preprocessed away to nothing, so your code will continue to work with any compiler. Of course HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATEDisn't the only warning Hedley knows about, nor is disabling warnings all Hedley can do, but hopefully you get the idea.
将禁用关于在 GCC、clang、ICC、PGI、MSVC、TI、IAR、ODS、Pelles 和可能的其他人上调用已弃用函数的警告(我可能不会在更新 Hedley 时费心更新这个答案)。而且,在未知的编译器上,宏将被预处理为空,因此您的代码将继续与任何编译器一起使用。当然,HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED这不是 Hedley 知道的唯一警告,也不是 Hedley 可以做的所有禁用警告,但希望您能明白。
回答by R.. GitHub STOP HELPING ICE
Rather than silencing the warnings, gcc style is usually to use either standard C constructs or the __attribute__extension to tell the compiler more about your intention. For instance, the warning about assignment used as a condition is suppressed by putting the assignment in parentheses, i.e. if ((p=malloc(cnt)))instead of if (p=malloc(cnt)). Warnings about unused function arguments can be suppressed by some odd __attribute__I can never remember, or by self-assignment, etc. But generally I prefer just globally disabling any warning option that generates warnings for things that will occur in correct code.
gcc 风格通常使用标准 C 构造或__attribute__扩展来告诉编译器更多关于您的意图的信息,而不是使警告静音。例如,通过将赋值放在括号中(即if ((p=malloc(cnt)))代替 )来抑制关于用作条件的赋值的警告if (p=malloc(cnt))。关于未使用的函数参数的警告可以通过一些__attribute__我不记得的奇怪或通过自赋值等来抑制。但通常我更喜欢全局禁用任何警告选项,这些选项会为将在正确代码中发生的事情生成警告。
回答by Keron
For those who found this page looking for a way to do this in IAR, try this:
对于那些发现此页面以寻找在 IAR 中执行此操作的方法的人,请尝试以下操作:
#pragma diag_suppress=Pe177
void foo1( void )
{
/* The following line of code would normally provoke diagnostic
message #177-D: variable "x" was declared but never referenced.
Instead, we have suppressed this warning throughout the entire
scope of foo1().
*/
int x;
}
#pragma diag_default=Pe177
See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472m/chr1359124244797.htmlfor reference.
请参阅http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472m/chr1359124244797.html以供参考。

