#warning 预处理指令的可移植性

65

我知道 C/C++ 中的 #warning 指令并不是标准,但是包括 gcc/g++ 等在内的一些编译器支持它。但对于那些不支持它的编译器,它们会默默忽略它还是会导致编译失败?换句话说,如果我的项目中使用了 #warning 指令,那么是否可以在不破坏不支持它的编译器的构建的情况下安全地使用它?

6个回答

87

需要注意的是,MSVC使用以下语法:

#pragma message ( "your warning text here" )

通常的#warning语法会生成致命错误:

C1021: invalid preprocessor command 'warning'

因此,该语法对于那些编译器来说不具有可移植性。


29
这是少有的情况之一,微软做事方式正确。 - mip
2
刚刚使用gcc-4.7.2进行了快速检查。[$ gcc -c -Werror file.c] 产生 [file.c:10:9: 注意:#pragma message: Foo bar baz],所以它生成了一个“注释”,但不被视为警告(即启用-Werror不会导致构建失败)。但它似乎正确解析了(因为所有的#pragma都应该这样),所以从这个意义上来说它是可移植的。 - nolandda
6
在MSVC 2008中,#pragma message不会生成警告,它只是将文本输出到“构建日志”中。因此,例如,在“错误列表”窗口中不会显示它,也不会增加警告总数。 - nevermind
11
如果你在消息中加入“warning”,那么它仍然算作一条警告信息,例如:#pragma message("warning: foo")。 - jheriko
3
顺带一提,这个语法在OpenWatcom中也可以使用。(是的,我顶了一个旧的帖子。人们将永远通过谷歌搜索这样的内容。) - JustJeff
显示剩余3条评论

31

如果编译器不支持 #warning,那么它很可能会发出一个错误。与 #pragma 不同的是,预处理程序没有建议忽略它不理解的指令。

话虽如此,我在各种不同(相当普遍的)平台上使用过编译器,并且它们都支持 #warning。


12
看起来你从未尝试过 MS Visual Studio Professional 2015 ;-). - Peter - Reinstate Monica
50
@PeterA.Schneider: 当然在2008年我还没有! - Greg Hewgill

3

当从MinGW转换到Visual Studio时,在我的全局配置头文件中添加了以下内容。(在stdafx.h中包含)

#ifdef __GNUC__
//from https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
//Instead of put such pragma in code:
//#pragma GCC diagnostic ignored "-Wformat"
//use:
//PRAGMA_GCC(diagnostic ignored "-Wformat")
#define DO_PRAGMA(x) _Pragma (#x)
#define PRAGMA_GCC(x) DO_PRAGMA(GCC #x)

#define PRAGMA_MESSAGE(x) DO_PRAGMA(message #x)
#define PRAGMA_WARNING(x) DO_PRAGMA(warning #x)
#endif //__GNUC__
#ifdef _MSC_VER
/*
#define PRAGMA_OPTIMIZE_OFF __pragma(optimize("", off))
// These two lines are equivalent
#pragma optimize("", off)
PRAGMA_OPTIMIZE_OFF
*/
#define PRAGMA_GCC(x)
// https://support2.microsoft.com/kb/155196?wa=wsignin1.0
#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
#define __PRAGMA_LOC__ __FILE__ "("__STR1__(__LINE__)") "
#define PRAGMA_WARNING(x) __pragma(message(__PRAGMA_LOC__ ": warning: " #x))
#define PRAGMA_MESSAGE(x) __pragma(message(__PRAGMA_LOC__ ": message : " #x))

#endif

//#pragma message "message quoted"
//#pragma message message unquoted

//#warning warning unquoted
//#warning "warning quoted"

PRAGMA_MESSAGE(PRAGMA_MESSAGE unquoted)
PRAGMA_MESSAGE("PRAGMA_MESSAGE quoted")

#warning "#pragma warning quoted"

PRAGMA_WARNING(PRAGMA_WARNING unquoted)
PRAGMA_WARNING("PRAGMA_WARNING quoted")

现在我使用 PRAGMA_WARNING(这需要修复)

遗憾的是,在gcc中没有#pragma warning,因此它会警告未指定的编译指示。

我怀疑gcc是否会添加#pragma warning"而不是微软添加#warning


目前boost支持BOOST_PRAGMA_MESSAGE。 - Fantastory
使用GCC,这是:#pragma GCC warning "警告信息" - Sébastien Bémelmans

3
您可能会收到至少一个未被识别的指令警告,来自于不认识 #warning 的编译器,即使代码块没有被包含在您的编译中。这可能会被视为错误 - 编译器可能会合法地将其视为错误,但许多编译器会更加宽松。
除了GCC/G++之外,您是否知道(能否命名)提供 #warning 的其他编译器?[编辑:Sun Solaris 10(Sparc)和Studio 11 C/C++编译器都接受 #warning。]

1

我曾经遇到过一个Atmel处理器的编译器问题。由于未知的 #warning 标记,它会生成预处理器错误。

不幸的是,解决方案似乎是将整个源代码树转换为使用 #pragma 等效项,并接受如果使用 gcc,则构建行为会有所不同。


0
实际上,据我了解,大多数编译器都会忽略未知的 #pragma 指令,并输出一个警告信息 - 所以在最坏的情况下,你仍然会得到一个警告。

7
然而,#warning并不是一个#pragma。 - Greg Hewgill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接