编译器版本号的gcc预定义宏是什么?

36

我遇到了gcc v3.4.4的bug,并希望在我的代码中加入#ifdef来解决这个版本编译器的bug。

如何使用GCC编译器预处理器预定义宏来检测编译器的版本号?


1
可能是如何测试当前版本的GCC?的重复问题,适用于通用C / C ++。 - Ciro Santilli OurBigBook.com
5个回答

46

来自gnu cpp手册...


__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__

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

__GNUC_PATCHLEVEL__ 是 GCC 3.0 中新引入的;在 3.0 前广泛使用的开发快照中也存在(这些快照自称为 GCC 2.96 或 2.97,具体取决于您拥有的快照版本)。

如果您只需要知道您的程序是否由 GCC 编译,或者由声称接受 GNU C 方言的非 GCC 编译器编译,则可以简单地测试 __GNUC__。如果您需要编写依赖于特定版本的代码,则必须更加小心。每次增加次要版本时,补丁级别将重置为零;每次增加主要版本(这很少发生)时,次要版本和补丁级别都会重置。如果您希望直接在条件语句中使用预定义的宏,则需要编写如下代码:

          /* Test for GCC > 3.2.0 */
          #if __GNUC__ > 3 || \
              (__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \
                                 (__GNUC_MINOR__ == 2 && \
                                  __GNUC_PATCHLEVEL__ > 0)))

1
是我还是clang也有相同的__GNUC__定义?所以这不是gcc的真正测试吗? - Bram

21

__GNUC____GNUC_MINOR____GNUC_PATCHLEVEL__

例如,GCC 4.0.1 将会:

#define __GNUC__ 4
#define __GNUC_MINOR__ 0
#define __GNUC_PATCHLEVEL__ 1

当你想知道在当前编程环境下GNU GCC编译器所定义的预定义预处理指令时,可以记住以下这个简单的命令行:

gcc -E -dM - < /dev/null |less


4
GCC 预定义预处理器指令的技巧不错。按字母顺序排序更好: gcc -E -dM - < /dev/null | sort | less - Bart
谢谢您的提示 - 运行“gcc -E -dM - < /dev/null”非常有帮助! - Phil
你如何在Windows上生成它们? - Royi

4

有3个gcc版本的宏可供测试。

__GNUC_MINOR__ 
 __GNUC_PATCHLEVEL__ 
 __GNUC__ 

例如,我的gcc版本为4.3.1,将它们定义为这样:
#define __GNUC_MINOR__ 1
#define __GNUC_PATCHLEVEL__ 3
#define __GNUC__ 4

您可以通过运行以下命令来查看定义的“内置”宏:

gcc -E -dM -x c /dev/null

该命令与C语言编译器相关,可用于显示当前环境中定义的所有预定义宏。

2
在线文档中得知: __GNUC__,__GNUC_MINOR__和__GNUC_PATCHLEVEL__是由使用C预处理器的所有GNU编译器(包括C、C++、Objective-C和Fortran)定义的宏。它们的值是编译器的主要版本号、次要版本号和修补程序级别,以整数常量表示。例如,GCC 3.2.1将会把__GNUC__定义为3,__GNUC_MINOR__定义为2,__GNUC_PATCHLEVEL__定义为1。如果直接调用预处理器,则也会定义这些宏。
另外一个宏__VERSION__扩展为描述所使用编译器版本的字符串常量。您不应该依赖其内容具有任何特定形式,但可以确保至少包含发布号。

0

顺便提一下,如果您正在使用glib,则可以访问以下宏,该宏可用于检查GNU C/C++编译器版本:

#ifdef __GNUC__
#define G_GNUC_CHECK_VERSION(major, minor) \
    ((__GNUC__ > (major)) || \
     ((__GNUC__ == (major)) && \
      (__GNUC_MINOR__ >= (minor))))
#else
#define G_GNUC_CHECK_VERSION(major, minor) 0
#endif

请注意,当您未使用GNU编译器时,该宏始终返回false(0)。
因此,在我的snapdev library version.h header中,我使用以下宏。在我的情况下,我还想检查补丁,并且我使用了许多库,因此我编写了一个更通用的版本:
#define     SNAPDEV_CHECK_VERSION(wanted_major, wanted_minor, wanted_patch, current_major, current_minor, current_patch) \
                (((current_major) > (wanted_major)) || \
                    (((current_major) == (wanted_major)) \
                        && (((current_minor) > (wanted_minor)) || \
                            (((current_minor) == (wanted_minor)) \
                                && ((current_patch) >= (wanted_patch))))))

我有一个专门为GCC设计的检查,因此您不必记住包括版本在内的宏名称:

#define     SNAPDEV_CHECK_GCC_VERSION(wanted_major, wanted_minor, wanted_patch) \
                SNAPDEV_CHECK_VERSION(wanted_major, wanted_minor, wanted_patch, \
                                      __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)

就像我对我的大部分代码一样,我编写了一个单元测试,这样我就可以说,除非您提供无效数据(臭名昭著的最后一句话),否则测试不太可能失败。


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