转载:gcc中预定义的宏__GNUC__ - Cccarl - 博客园 (cnblogs.com)

今天在看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

__GNUC__ 、__GNUC_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进行编写代码,至于其他预定义的宏呢可以去本文刚开始的时候给出的网站上查看,他们各自的作用也都写的非常清楚。

gcc中预定义的宏__GNUC__的更多相关文章

  1. visual c++中预定义的宏

    一.主要目标 (由于visual studio通常包含很多开发环境,通常将其中c/c++的ide称为visual c++ 20xx) 整理下visual c++ 2010下预定义的宏.做一下备忘和了解 ...

  2. ARM编译器中预定义的宏

    arm系列目前支持三大主流的工具链,realview的armcc,iar ewarm的iccarm,gnu的gcc,编译器在编译的时候会预定义一些宏,这些宏在工程中起到不可或缺的作用. 例如 /* d ...

  3. C++中预定义的宏

    以下信息摘自与标准C++的文档中. 如果把这些宏加在程序的日志中,它将为开发人员进行问题分析提供了很好的帮助. standard c++ 1998版The following macro names ...

  4. C标准中一些预定义的宏

    C标准中指定了一些预定义的宏,对于编程经常会用到.下面这个表中就是一些常常用到的预定义宏. 宏(双下滑线) 意义 __DATE__ 进行预处理的日期(“Mmm dd yyyy”形式的字符串文字) __ ...

  5. C标准中一些预定义的宏,如__FILE__,__func__等

    C标准中一些预定义的宏 C标准中指定了一些预定义的宏,对于编程经常会用到.下面这个表中就是一些常常用到的预定义宏. 宏 意义 __DATE__ 进行预处理的日期(“Mmm dd yyyy”形式的字符串 ...

  6. VS2013 预定义的宏

    Visual Studio 2013 预定义的宏 https://msdn.microsoft.com/zh-cn/library/b0084kay(v=vs.120).aspx 列出预定义的 ANS ...

  7. 2019-8-31-dotnet-新项目格式与对应框架预定义的宏

    title author date CreateTime categories dotnet 新项目格式与对应框架预定义的宏 lindexi 2019-08-31 16:55:58 +0800 201 ...

  8. dotnet 新项目格式与对应框架预定义的宏

    在 sdk style 的项目格式支持使用多框架开发,此时需要在代码里面通过宏判断,在编译的时候执行不同的代码.本文告诉大家在框架里面对应的预定义的条件编译符有哪些 在让一个 csproj 项目指定多 ...

  9. 五个在XML文档中预定义好的实体

    下面是五个在XML文档中预定义好的实体: < < 小于号 > > 大于号 & & 和 &apos; ' 单引号 " " 双引号 实体 ...

随机推荐

  1. Linux上合理设置网卡的MTU值

    MTU:是网络的最大传输单元,通信术语:最大传输单元(Maximum Transmission Unit,MTU)是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位).最大传输单元这个 ...

  2. Dockerfile 自动制作 Docker 镜像(一)—— 基本命令

    Dockerfile 自动制作 Docker 镜像(一)-- 基本命令 前言 a. 本文主要为 Docker的视频教程 笔记. b. 环境为 CentOS 7.0 云服务器 c. 上一篇:手动制作Do ...

  3. Python与Mysql 数据库的连接,以及查询。

    python与mysql数据库的连接: pymysql是python中对数据库的连接模块:因此应当首先安装pymysql数据库模块. 执行pip install pymysql 命令. 然后在pyth ...

  4. Apache Dolphin Scheduler - Docker Compose 详解

    Apache DolphinScheduler 是一个分布式去中心化,易扩展的可视化 DAG 工作流任务调度系统.简称 DS,包括 Web 及若干服务,它依赖 PostgreSQL 和 Zookeep ...

  5. [PhpStorm]解决Cannot find declaration to go to

    1.问题重现 使用单例模式访问类方法,PhpStorm提示类方法Cannot find declaration to go to 2.解决方法 加一句代码注释 注意:注释不能省略变量名 注:成员变量实 ...

  6. dede5.7 给栏目添加上缩略图

    如我们一个栏目列表都用缩略图来表示,而不仅仅只是文字,如果没有这项功能会非常麻烦,网上有很多这方面的资料,但是都试过了有很多问题,自己研究一下,测试基本通过.新加字段 typeimg后台执行SQL: ...

  7. 对帧率、I/P率、I帧间隔的理解

    码率就是数据传输时单位时间传送的数据位数,一般我们用的单位是kbps即千位每秒.通俗一点的理解就是取样率,单位时间内取样率越大,精度就越高,处理出来的文件就越接近原始文件,但是文件体积与取样率是成正比 ...

  8. Jupyter lab 配置记录,xpython + R 语言

    install.packages(c("repr", "IRdisplay", "evaluate", "crayon" ...

  9. HTML 网页开发、CSS 基础语法——三. HTML概念

    1.纯文本格式 纯文本格式,就是没有任何文本修饰的,没有任何粗体,下划线,斜体,图形,符号,或者特殊字符,及特殊打印格式的文本,只保存文本,不保存其格式设置. ①格式对比 纯文本格式 富文本格式 最常 ...

  10. P3214-[HNOI2011]卡农【dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P3214 题目大意 一个由\(1\sim n\)的所有整数构成的集合\(S\),求出它的\(m\)个不同非空子集满足 ...