使用宏检测gcc而不是msvc/clang

Val*_*ris 43 c++ gcc

我正在开发一个迄今为止用gcc和msvc构建的项目.我们最近也开始用clang构建.

代码中有一些部分,其中特定于平台的事情已经完成:

#ifndef _WIN32
// ignore this in msvc
#endif
Run Code Online (Sandbox Code Playgroud)

由于gcc以前是唯一的非windows构建,这相当于说"只为gcc做这个".但现在它意味着"只为gcc和clang做这个".

然而,仍然有一些情况,我想专门为gcc处理一些东西,而不是为了clang.是否有一种简单而强大的方法来检测gcc,即

#ifdef ???
// do this *only* for gcc
#endif
Run Code Online (Sandbox Code Playgroud)

dmg*_*dmg 63

__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
Run Code Online (Sandbox Code Playgroud)

这些宏由所有使用C预处理器的GNU编译器定义:C,C++,Objective-C和Fortran.它们的值是编译器的主要版本,次要版本和补丁级别,作为整数常量.例如,GCC 3.2.1将__GNUC__定义为3,__ GNUC_MINOR__定义为2,并将__GNUC_PATCHLEVEL__定义为1.如果直接调用预处理器,也会定义这些宏.

也:

__GNUG__
Run Code Online (Sandbox Code Playgroud)

GNU C++编译器定义了这个.测试它相当于测试(__GNUC__ && __cplusplus).

资源

显然,也clang使用它们.但它也定义了:

__clang__
__clang_major__
__clang_minor__
__clang_patchlevel__
Run Code Online (Sandbox Code Playgroud)

所以你可以这样做:

#ifdef __GNUC__
    #ifndef __clang__
...
Run Code Online (Sandbox Code Playgroud)

甚至更好(注意顺序):

#if defined(__clang__)
....
#elif defined(__GNUC__) || defined(__GNUG__)
....
#elif defined(_MSC_VER)
....
Run Code Online (Sandbox Code Playgroud)

  • 这些东西都收集在更强大的[Boost.Predef](http://www.boost.org/doc/libs/release/libs/predef/doc/html/index.html)和(现在已经过时) )Boost库所在的原始wiki [这里](http://sourceforge.net/p/predef/wiki/Compilers/).请注意,英特尔编译器也会在相关平台上定义`__GNUC__`或`_MSC_VER`. (3认同)
  • 所有支持 GNU C 语言扩展集的编译器都定义了这些宏,直到`__GNUC_PATCHLEVEL__`。因此,要在任何编译器上检测对特定 GNU C 功能的支持,您可以检查这些宏。在 gcc 本身上,它们也映射到您正在使用的编译器的实际版本,但它们最好用于告诉您支持哪个版本的 GNU C 语言,而不是编译器类型/版本。 (2认同)

Val*_*ris 9

使用Boost,这变得非常简单:

#include <boost/predef.h>

#if BOOST_COMP_GNUC
// do this *only* for gcc
#endif
Run Code Online (Sandbox Code Playgroud)

另请参阅boost文档的使用predefs部分.

(信贷rubenvb谁在评论中提到这一点,阿尔贝托M代表加入包括,和弗雷德里克Aalund修正#ifdef#if)

  • 您应该使用“#if BOOST_COMP_GNUC”而不是“#ifdef”,因为该宏“始终”已定义(但可能为零)。请参阅http://www.boost.org/doc/libs/1_66_0/doc/html/predef/using_the_predefs.html (2认同)
  • 请注意,使用 Boost 并不总是正确的解决方案。Boost确实很方便,但由于它的大小和复杂性,会增加大量的开销。# (2认同)

Kha*_*hal 9

我使用这个定义:

#define GCC_COMPILER (defined(__GNUC__) && !defined(__clang__))
Run Code Online (Sandbox Code Playgroud)

并用它测试:

#if GCC_COMPILER
...
#endif
Run Code Online (Sandbox Code Playgroud)

  • 那不会排除ICC。 (4认同)
  • @Ayxan:因为 ICC 支持 GNU 扩展,因此定义了`__GNUC__`。您还必须检查 `!defined(__INTEL_COMPILER)`,例如 clang。https://software.intel.com/en-us/forums/intel-c-compiler/topic/281802 (3认同)