__GNUC__
并不特指 GCC。所有支持 GNU C 扩展的编译器都定义了它,包括 clang 和 ICC。
专门检测 GCC 的正常方法是排除其他“兼容”编译器
#if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER)
#define REAL_GCC __GNUC__ // probably
#endif
Clang 前端定义__clang__
,但是其他使用 LLVM 后端的前端也定义了__llvm__
(例如 IBM XL C/C++ 版本 13.1.1 到 16.1)。最好排除__clang__
代替__llvm__
,取决于您想要排除它的原因。 (例如,出于解析原因,与出于优化原因(例如 LLVM 评估)__builtin_constant_p()
在进行内联之前,因此它在内联函数的参数上毫无用处。)
也可以看看https://sourceforge.net/p/predef/wiki/Compilers/ https://sourceforge.net/p/predef/wiki/Compilers/对于一个大列表。
https://blog.kowalczyk.info/article/j/guide-to-predefined-macros-in-c-compilers-gcc-clang-msvc-etc..html https://blog.kowalczyk.info/article/j/guide-to-predefined-macros-in-c-compilers-gcc-clang-msvc-etc..html也出现在谷歌结果中,但不太完整。
您应该抱怨的是,GCC 本身没有定义您可以检测到的特定于 GCC 的宏,仅定义了它支持的 GNU C 方言的版本。 (GNU C 是一种语言,GCC 是该语言的编译器。 GCC's __GNUC_MINOR__
/ __GNUC_PATCHLEVEL__
不幸的是,宏将两者混为一谈。)
Clang 定义__GNUC__
/ __GNUC_MINOR__
/ __GNUC_PATCHLEVEL__
根据它声称完全兼容的 gcc 版本。 (可能仅适用于 GCC 文档保证可以工作的内容,不适用于恰好与该版本或更高版本的 gcc 一起工作的内容。对于 GCC 本身,记录=支持。
被编译器接受并不意味着它受到未来 GCC 版本的支持和保证。这可能就是 clang 声称支持某些 GNU C 版本的理由)。
例如,clang 7.0.1将GNUC/MINOR/PATCHLEVEL定义为4/2/1,即与GCC 4.2.1兼容
例如从海湾合作委员会手册 https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
…
/* Test for GCC > 3.2.0 */
#if GCC_VERSION > 30200
如果您正在测试最近的 GCC 支持但最近的 clang 还不支持的特定 GNU C 功能,那么您可能应该这样做。