在Visual c++中,可以使用#pragma warning (disable:…)我还发现,在GCC中,您可以覆盖每个文件编译器标志。我怎么能做到这一点为“下一行”,或与推/弹出语义周围的代码区域使用GCC?


当前回答

TL;DR:如果它工作,避免,或使用像_Noreturn, [[nodiscard]], __attribute__这样的说明符,否则_Pragma。

这是我博客文章的一个简短版本 GCC和Clang中的抑制警告。

考虑下面的Makefile,

CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror

.PHONY: all
all: puts

构建下面的put .c源代码:

#include <stdio.h>

int main(int argc, const char *argv[])
{
    while (*++argv)
        puts(*argv);
    return 0;
}

它将无法编译,因为argc未使用,并且设置是核心的(-W -Wall -pedantic -Werror)。

你可以做以下五件事:

如果可能的话,改进源代码 使用一个属性,比如[[maybe_unused]] 使用声明说明符,如__attribute__ 使用_Pragma 使用# pragma 使用命令行选项。

改进源代码

第一次尝试应该是检查源代码是否可以改进以消除警告。在这种情况下,我们不想仅仅因为这一点而改变算法,因为argc对于!*argv(最后一个元素后为NULL)是多余的。

使用属性,如[[maybe_unused]]

#include <stdio.h>

int main([[maybe_unused]] int argc, const char *argv[])
{
    while (*++argv) puts(*argv);
    return 0;
}

如果幸运的话,标准为您的情况提供了一个属性,如[[maybe_unused]]。属性是C2x的新特性。到目前为止,C2x定义了四个属性,[[deprecated]]、[[fallthrough]]、[[maybe_unused]]和[[nodiscard]]。

使用声明说明符,如__attribute__

#include <stdio.h>

int main(__attribute__((unused)) int argc, const char *argv[])
{
    while (*++argv) puts(*argv);
    return 0;
}

如果幸运的话,标准为您的情况提供了一个说明符,如_Noreturn。

__attribute__是GCC专有扩展(Clang和一些其他编译器,如armcc也支持),许多其他编译器无法理解。如果你想要可移植的代码,将__attribute__((未使用))放在宏中。

_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")

_Pragma操作符的主要优点是你可以把它放在宏中,而#pragma指令是不可能做到的。

缺点:它几乎是一个战术核武器,因为它是基于行而不是基于声明的。

_Pragma操作符是在C99中引入的。

# pragma directive。

我们可以更改源代码来抑制对代码区域(通常是整个函数)的警告:

#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

缺点:它几乎是一个战术核武器,因为它是基于行而不是基于声明的。

注意,Clang中也存在类似的语法。

对单个文件取消命令行上的警告

我们可以在Makefile中添加下面这行代码来抑制针对看跌期权的警告:

CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror

.PHONY: all
all: puts

puts.o: CPPFLAGS+=-Wno-unused-parameter

在你的特定情况下,这可能不是你想要的,但它可能会帮助其他有类似情况的读者。

其他回答

这是一个暂时禁用警告的例子:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
    write(foo, bar, baz);
#pragma GCC diagnostic pop

您可以查看GCC诊断指南文档以获得更多详细信息。

我有同样的问题与外部库,如ROS头。我喜欢在CMakeLists.txt中使用以下选项进行更严格的编译:

set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -Wextra -Wstrict-aliasing -pedantic -Werror -Wunreachable-code ${CMAKE_CXX_FLAGS}")

然而,这样做也会在外部包含的库中导致各种迂腐的错误。解决方案是在包含外部库之前禁用所有迂迂的警告,并像这样重新启用它们:

// Save compiler switches
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"

// Bad headers with a problem goes here
#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>

// Restore compiler switches
#pragma GCC diagnostic pop

这似乎是可以做到的。我无法确定它添加的GCC版本,但它是在2010年6月之前的某个时候。

这里有一个例子:

#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 */
#pragma GCC diagnostic ignored "-Wformat"

将"-Wformat"替换为警告标志的名称。

AFAIK,这个选项没有办法使用push/pop语义。

在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

参考官方文件。