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__);
#endif
    
    return 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 > 30200
    printf("gcc > 3.2.0\n");
    //...
#endif
    return 0;
}

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

 

 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/whatday/article/details/101855136

智能推荐

贝尔数-程序员宅基地

文章浏览阅读2.3k次。转自ACdreamer http://blog.csdn.net/acdreamers/article/details/12309269Bell数的定义:第n个Bell数表示集合{1,2,3,...,n}的划分方案数,即:B[0] = 1; 每一个Bell数都是第二类Stirling数的和,即: 第二类Stir_贝尔数

Spring MVC访问页面直接显示源码_springmvc加载jsp为什么是源码-程序员宅基地

文章浏览阅读5.3k次,点赞5次,收藏6次。一、问题描述SSM整合好之后,通过Controller,返回要访问页面的url,然后jsp页面显示,问题是jsp页面直接把源码显示了!!如下二、解决方法出现这种问题是由于我在web.xml中把url-pattern配置错了,所导致的,我配置的如下: SpringMVC /* 把他改成 S_springmvc加载jsp为什么是源码

@aspect注解类不生效_自定义注解加AOP怎么玩?-程序员宅基地

文章浏览阅读719次。点击阅读原文更好的阅读体验前言注解是在JDK1.5之后引入的新特性位于java.lang.annotation,注解其实就是对代码进行一种特殊的标记,这些标记可以在编译,类加载和运行时被读取,并执行相应的处理。本文主要分析如何自定义注解和注解的一些基础知识,然后在配合这AOP在实际运用中玩出新花样。本文分为三部分注解分析自定义注解编译时注解运行时注解整合AOP原本可以分为两篇文章,但是想..._aspect类名有些不生效

opencv学习笔记 读取avi视频_cv 读取avi-程序员宅基地

文章浏览阅读985次。#include "cv.h"int main( int argc, char** argv ) { cvNamedWindow( "Example2", CV_WINDOW_AUTOSIZE ); //CvCapture* capture = cvCaptureFromAVI( argv[1] ); // either one will work CvCapt_cv 读取avi

百度地图SDK提供的地图类型和图层的实现_百度sdk里包含地图吗-程序员宅基地

文章浏览阅读551次。1.环境搭建(参考上一次的文章)2.百度地图SDK提供了3种预置的地图类型,包括普通地图,卫星图,空白地图。另外提供了2种常用图层实时路况图以及百度城市热力图。其中要注意的是百度地图SDK所提供的地图缩放等级为4-21级(室内图可以缩放至22级,卫星图只支持缩放到20级),只有在地图层级介于11-20级时,方可显示城市热力图。3.较完整地代码实现activity_main.xml源码<..._百度sdk里包含地图吗

klocwork insight V12 12.x v11.x v10.x安装过程_kgomultispace框架-程序员宅基地

文章浏览阅读3.7k次。静态代码缺陷检查工具沟通学习交流,如klocwork,coverity,testbed,chckmarx,fortify,webinspect,appscan等。_kgomultispace框架

随便推点

非常详细的相机标定原理(四)(张正友相机标定法数学推导求解)_张正有标定法 最少要几张图片-程序员宅基地

文章浏览阅读2.3k次,点赞10次,收藏32次。解释单应性矩阵H 1.H是内参矩阵和外参矩阵的混合体:2.先不考虑镜头畸变: 3.旋转向量在构造中是相互正交: 4.—个单应性矩阵H可以提供上述两个约束条件5.B带入前面两个约束条件后可转化为 6.两约束条件最终可以转化为如下形式: 7.通过以上的公式推导做铺垫,求相机内参数。8. 求相机外参9.奇异值分解10. 考虑透镜畸变的影响......_张正有标定法 最少要几张图片

ESP8266 SDK开发的低版本程序迁移到高版本的方法_esp8266 sdkv2.0.x的app移植到sdkv3.0.0-程序员宅基地

文章浏览阅读526次。ESP8266 SDK开发的低版本程序迁移到高版本的方法前言:目前AiThinkerIDE_开发环境版本为V1.5.2,低版本为V0.5和V1.0版,如何将低版本开发的程序,如SDK2.2以下的程序迁移到目前高版本SDK3.04(版本更新为2020年6月)环境,如果直接编译,出错。试了试,可按如下方法来进行。1.打开AiThinkerIDE_V1.5.2,输入官方SDK包ESP8266_NONOS_SDK-3.0.4和在AiThinkerIDE V0.5环境下开发的SDK程序,如ESP8266_NON_esp8266 sdkv2.0.x的app移植到sdkv3.0.0

vue接入vlc播放rtsp视频流_vue调用vlc 公开的rpst-程序员宅基地

文章浏览阅读1.9w次。&lt;object type='application/x-vlc-plugin' id='vlc' events='True' classid='clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921' codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/a..._vue调用vlc 公开的rpst

JDBC之DatabaseMetaData之获取表的所有列名_databasemetadata接口获取的列名不对-程序员宅基地

文章浏览阅读1.1w次,点赞6次,收藏9次。获取数据库指定表的所有列及相应的信息:(以MySQL和Oracle为例,其他类型的数据库接触不多,不做解释)Connection接口中提供了DatabaseMetaData接口:提供:getColumns()方法,该方法需要传进4个参数:第一个是数据库名称,对于MySQL,则对应相应的数据库,对于Oracle来说,则是对应相应的数据库实例,可以不填,也可以直接使用Connectio_databasemetadata接口获取的列名不对

如何在交换机上抓包_交换机抓包-程序员宅基地

文章浏览阅读3.1w次,点赞18次,收藏128次。在交换机上抓包,一般可排查一些网络问题。下面是总结的在各厂商交换机上抓包方式。H3C交换机抓包:在华三交换机上可使用:packet-capture 命令,在用户视图下执行。具体操作可查看这:https://www.h3c.com/cn/d_202009/1327093_30005_0.htm#做流统匹配抓包流量acl advanced 3000description test rule 0 permit ip source 192.168.1.1 0 destination 192.168_交换机抓包

推荐文章

热门文章

相关标签