gcc中预定义的宏__GNUC__

今天在看Linux系统编程这本书的代码的时候看到了__GNUC__,不太清楚这个宏所以去查了一下,以此记录。GNU C预定义了一系列的宏,这些宏都是以双下划线开始的,这里只讲一下__GNUC__ GNUC_MINOR GNUC_PATCHLEVEL,其他GNU C的预定义宏可以到这里查看:
https://gcc.gnu.org/onlinedocs/gcc-5.1.0/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros
GNUCGNUC_MINOR 、__GNUC_PATCHLEVEL__分别代表gcc的主版本号,次版本号,修正版本号。这里引用一下上面的官方说明:

GNUC

GNUC_MINOR

GNUC_PATCHLEVEL

These macros are defined by all GNU compilers that use the C preprocessor: C, C++, Objective-C and Fortran. Their values are the major version, minor version, and patch level of the compiler, as integer constants. For example, GCC 3.2.1 will define GNUC to 3, GNUC_MINOR to 2, and GNUC_PATCHLEVEL to 1. These macros are also defined if you invoke the preprocessor directly.

GNUC_PATCHLEVEL is new to GCC 3.0; it is also present in the widely-used development snapshots leading up to 3.0 (which identify themselves as GCC 2.96 or 2.97, depending on which snapshot you have).

If all you need to know is whether or not your program is being compiled by GCC, or a non-GCC compiler that claims to accept the GNU C dialects, you can simply test GNUC. If you need to write code which depends on a specific version, you must be more careful. Each time the minor version is increased, the patch level is reset to zero; each time the major version is increased (which happens rarely), the minor version and patch level are reset. If you wish to use the predefined macros directly in the conditional, you will need to write it like this:

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

Another approach is to use the predefined macros to calculate a single number, then compare that against a threshold:

      #define GCC_VERSION (__GNUC__ * 10000 \
                           + __GNUC_MINOR__ * 100 \
                           + __GNUC_PATCHLEVEL__)
      ...
      /* Test for GCC > 3.2.0 */
      #if GCC_VERSION > 30200

Many people find this form easier to understand.

上面这一大段英语实际是在讲:

注意,__GNUC_PATCHLEVEL__是从gcc 3.0以后才有的,在这之前的gcc是没有预定义这个宏的。我们可以用gcc --version来查看自己系统中的gcc版本,现在的gcc版本普遍都是3.0以后了吧,就我的系统而言,是4.9.2,那么对应的__GNUC__就是4,__GNUC_MINOR__就是9,__GNUC_PATCHLEVEL__就是2。这几个宏的类型都是int,被扩展后,会得到整数的字面值。由于是宏,因此我们可以通过只预处理源程序来观察他们的文本值。比如,只对下面这段代码进行预处理,预处理(gcc -E)以后是对宏进行直接的替换,所以我们就能看到这三个宏的文本值:

#include <stdio.h>

int main()
{
#ifdef __GNUC__
    printf("__GNUC__ = %d\n",__GNUC__); 
#endif
#ifdef __GNUC_MINOR__
    printf("__GNUC_MINOR__ = %d\n",__GNUC_MINOR__); 
#endif
#ifdef __GNUC_PATCHLEVEL__
    printf("__GNUC_PATCHLEVEL__ = %d\n",__GNUC_PATCHLEVEL__);
#endif
    
    return 0;
}

预编译以后的文件函数部分:

# 942 "/usr/include/stdio.h" 3 4

# 2 "test.c" 2

int main()
{

    printf("__GNUC__ = %d\n",4);


    printf("__GNUC_MINOR__ = %d\n",9);


    printf("__GNUC_PATCHLEVEL__ = %d\n",2);


    return 0;
}

这样就很直观地看到,__GNUC__被替换成了4,__GNUC_MINOR__被替换成了9,__GNUC_PATCHLEVEL__替换成了2。

为什么要预定义了这三个宏呢?这是为了方便我们在针对特定版本的gcc编译器进行代码编写的,比如我们的代码要求gcc的版本至少在3.2.0以上,我们就可以写成如下方式的条件编译:

/* Test for GCC > 3.2.0 */
#if __GNUC__ > 3 || \
  (__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \
    (__GNUC_MINOR__ == 2 && \
      __GNUC_PATCHLEVEL__ > 0)))
  printf("gcc > 3.2.0\n");  //...
#endif

注意上面把条件编译#if的条件写成了多行的时候(和宏定义一样,如果宏定义一行写不完,要在最后加一个行继续符’’),每行最后的行继续符’‘后面不能跟任何符号,空格、制表符等都不行,他表示下一行的也是并列条件(通常为||或&&的右操作数),通常在编译以前会把行继续符’'以及前面的换行符都去掉,这样就可以看作是同一行的了。

当然有的人觉得上面的条件那么大一串看起来非常不顺眼,理解起来也不容易,这时候我们可以自己定义一个宏GCC_VERSION用来表示gcc版本,原理也很简单就是把主版本号10000+次版本号100+修订版本号,最终用这个值来判断gcc的版本号:

#include <stdio.h>
#define GCC_VERSION (__GNUC__ * 10000 \
                   + __GNUC_MINOR__ * 100 \
                   + __GNUC_PATCHLEVEL__)
int main()
{
/* Test for GCC > 3.2.0 */
#if GCC_VERSION > 30200
    printf("gcc > 3.2.0\n");
    //...
#endif
    return 0;
}

好啦,对__GNUC__这个预定义的宏变量算是有了一个基本的了解,作用是用来针对特定版本的gcc进行编写代码,至于其他预定义的宏呢可以去本文刚开始的时候给出的网站上查看,他们各自的作用也都写的非常清楚。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#ifdef __GNUC__ 是用来判断当前编译器是否是 GNU 编译器的预处理指令。如果当前编译器是 GNU 编译器,那么这个条件判断就为真。 GNU 编译器的版本号可以通过来获取。__GNUC__ 表示主版本号,__GNUC_MINOR__ 表示次版本号,__GNUC_PATCHLEVEL__ 表示修订号。可以使用这些来获取 GNU 编译器的版本信息,比如可以使用 printf("__GNUC__ = %d\n",__GNUC__) 来打印主版本号。 在引用提到了一个条件判断的例子,(__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \ 这个条件判断表示如果 GNU 编译器的主版本号为 3,次版本号大于 2 或者修订号大于等于 3,那么条件判断为真。 需要注意的是,引用的第三个内容是一条注释,注释用来解释代码的作用或者提供一些额外的说明。这个注释并不与 #ifdef __GNUC__ 有直接关系。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [gcc预定__GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__](https://blog.csdn.net/qq_20853741/article/details/128768346)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [C语言--#、##、__VA_ARGS__ 和##__VA_ARGS__ 的使用](https://blog.csdn.net/weixin_35615495/article/details/117065976)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值