在Visual c++中,可以使用#pragma warning (disable:…)我还发现,在GCC中,您可以覆盖每个文件编译器标志。我怎么能做到这一点为“下一行”,或与推/弹出语义周围的代码区域使用GCC?
当前回答
GCC风格通常不是关闭警告,而是使用标准C结构或__attribute__扩展名来告诉编译器更多关于你的意图的信息。
例如,关于将赋值用作条件的警告通过将赋值放在括号中来抑制,即if ((p=malloc(cnt))而不是if (p=malloc(cnt))。
关于未使用函数参数的警告可以通过一些奇怪的__attribute__我永远都记不住,或者通过自赋值等来抑制。
但一般来说,我更喜欢全局禁用任何警告选项,这些选项会为正确的代码中发生的事情生成警告。
其他回答
GCC风格通常不是关闭警告,而是使用标准C结构或__attribute__扩展名来告诉编译器更多关于你的意图的信息。
例如,关于将赋值用作条件的警告通过将赋值放在括号中来抑制,即if ((p=malloc(cnt))而不是if (p=malloc(cnt))。
关于未使用函数参数的警告可以通过一些奇怪的__attribute__我永远都记不住,或者通过自赋值等来抑制。
但一般来说,我更喜欢全局禁用任何警告选项,这些选项会为正确的代码中发生的事情生成警告。
在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
参考官方文件。
Use:
#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
这应该做的伎俩GCC, Clang和MSVC。
它可以用例如:
DISABLE_WARNING(unused-variable,unused-variable,42)
[.... some code with warnings in here ....]
ENABLE_WARNING(unused-variable,unused-variable,42)
参见7 Pragmas,通过Pragmas和Pragma指令控制诊断,以及__pragma和_Pragma关键字了解更多细节。
你至少需要4.02版本才能使用GCC的这些代码,我不确定MSVC和Clang的版本。
看起来GCC的push pop pragma处理有点坏。如果再次启用警告,仍然会得到DISABLE_WARNING/ENABLE_WARNING块内部的警告。对于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
在你的特定情况下,这可能不是你想要的,但它可能会帮助其他有类似情况的读者。
这似乎是可以做到的。我无法确定它添加的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 */
推荐文章
- C多行宏:do/while(0) vs作用域块
- time_t最终的类型定义是什么?
- 我需要显式处理负数或零时,总和平方数字?
- 函数名周围的括号是什么意思?
- 用C语言创建自己的头文件
- 格式化IO函数(*printf / *scanf)中的转换说明符%i和%d之间的区别是什么?
- main()中的Return语句vs exit()
- 如果不是内存地址,C指针到底是什么?
- 我如何在Visual Studio中预处理后看到C/ c++源文件?
- 保护可执行文件不受逆向工程的影响?
- 在一台主机上有多个glibc库
- 从C语言的函数返回一个struct
- C99 'restrict'关键字的实际用法?
- 检查子字符串存在于C中的字符串中
- 禁用所有gcc警告