linux gcc 宏定义 __GNUC__ __GNUC_MINOR__ 版本区分
今天在看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_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__);
#endifreturn 0;
}
预编译以后的文件函数部分:
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 > 30200printf("gcc > 3.2.0\n");//...
#endifreturn 0;
}
好啦,对__GNUC__这个预定义的宏变量算是有了一个基本的了解,作用是用来针对特定版本的gcc进行编写代码,至于其他预定义的宏呢可以去本文刚开始的时候给出的网站上查看,他们各自的作用也都写的非常清楚。
linux gcc 宏定义 __GNUC__ __GNUC_MINOR__ 版本区分相关推荐
- linux shell 宏定义_Linux系统和Shell命令行简介,走上数据分析之路
122Linux系统和Shell命令行简介,走上数据分析之路 本节作者:刘永鑫 中国科学院遗传与发育生物学研究所 版本1.0.2,更新日期:2020年8月31日 本项目永久地址:https://git ...
- linux makefile 宏定义
0.前言 从学习C语言开始就慢慢开始接触makefile,查阅了很多的makefile的资料但总感觉没有真正掌握makefile,如果自己动手写一个makefile总觉得非常吃力.所以特意借助博客总结 ...
- linux arm64 宏定义,ARM64 芯片的 Jiffies 更新流程
最近在调试 arm64 机器时遇到了一个比较蛋疼的时钟问题,这个时钟问题会导致在部分机器类型上导致无法启动,为了深入了解并解决掉这个问题,特定决定研究一下整个 jiffies 的更新逻辑过程,本篇文章 ...
- linux c 宏定义 #define _GNU_SOURCE 含义
今天我必须要使用 basename 函数,使用man手册查询了一下这个函数 man 3 basename 发现一个奇怪的信息 名称 basename,dirname-分析路径名组件 简介 #inclu ...
- Linux如何查看信号宏定义,转 LINUX 调试宏定义
在include\linux下新建一个debug头文件debug_if.h,鉴于KERN_WARNING之类的宏 在include\linux\kernel.h,因此将debug_if.h包含到ker ...
- linux shell 宏定义_linux内核修炼之系统调用
fork()这个系统调用是有两个返回值的,在子进程中的返回值是0,在父进程中的返回值是PID,如下 图 fork一次 返回两次 关于0x80中断和特权级检查 在mian函数的sched_init()函 ...
- linux shell 宏定义_一篇教会你写90%的shell脚本
shell是外壳的意思,就是操作系统的外壳.我们可以通过shell命令来操作和控制操作系统,比如Linux中的Shell命令就包括ls.cd.pwd等等.总结来说,Shell是一个命令解释器,它通过接 ...
- linux驱动 打印变量,linux驱动 内核函数 变量 宏定义
insmod modprobe(自动检测 模块加载时需要的别的模块) rmmod 用户空间工具, 加载模块到运行中的内核以及去除它们. #include module_init(init_functi ...
- 你真的了解宏吗:浅谈宏定义(#define语句)
简单聊下宏呗 写在前面: 宏定义 语法 1. 宏的作用范围 2.宏替换的原则 4. 宏函数申明 5. 宏中的 "#" 和 "##" #的用法 ##的用法 6. ...
最新文章
- Python爬虫学习(1)
- python字符串与列表与运算_[Python学习笔记1]Python语言基础 数学运算符 字符串 列表...
- day 45 SQLAlchemy,和增删查改
- 苹果错误分析报告preferreuserinterface_20182019年苹果产业链分析报告
- 卷积神经网络反向传播算法
- 爬取天天基金排行榜上的基金信息
- 周鸿祎反流氓的基本商业逻辑(ZZ)
- 去掉任务栏中SATA硬盘的安全删除硬件图标
- 蓝桥杯2020年第十一届C/C++B组(第一次)省赛习题题解
- 2023年有哪些值得推荐的蓝牙耳机?小米|南卡|JBL等等高性价比蓝牙耳机推荐
- 旷视科技经典文字检测EAST
- 元素水平垂直居中的六种方式
- 玩客云通过openwrt作为旁路由
- Grapher如何显示与绘图线成角度的线图标签丨使用教程
- 计算机专业课科目,考研计算机专业课有哪些科目
- 594. 最长和谐子序列--Python
- 机器学习初级算法之决策树
- java顺序查找法 监视器_java算法:顺序查找(有监视哨和无监视哨)
- 线段树进阶之清风拂面
- 高科路由器有虚拟服务器设置吗,高科路由器怎么设置 -电脑资料