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

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

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

_GNUC__宏函数相关推荐

  1. linux 打印函数宏,linux内核中的嵌入式汇编宏函数

    在看linux内核代码时,常会遇到诸如:static inline _syscall0(int,fork)这样的函数.经查阅资料,发现该函数是嵌入式汇编宏函数. linux内核提供了7个非常有用的宏定 ...

  2. python展开 c函数中的宏预处理_最基本的宏函数 课后习题9.2 (C语言代码)

    解题思路 利用宏函数. 函数. 本题的难点肯定不在算法, 应该是宏函数! 带参宏定义的一般形式为:#define 宏名(形参表) 字符串; 在字符串中含有各个形参. 带参宏调用的一般形式为: #def ...

  3. Report Studio值提示通过prompt宏函数给sql查询传参

    场景:当我们在DW中新建了一个表,但是在FM中没有创建模型,想针对这个表直接做一个报表,那么就需要在reportstudio中直接用sql来查询,为了追求查询速度,我们可以把页面用户选择的条件直接传给 ...

  4. c/c++宏函数的定义与使用(宏定义函数)(macro definition)

    文章目录 为什么要使用宏函数? 什么是宏 如何使用宏 宏的定义 不带参数的宏 带参数的宏(假参数,不是真正的参数,只是替换而已) 原理 对了,如果宏函数与函数名称相同,优先使用宏定义函数 为什么要使用 ...

  5. #define定义宏函数 的正确使用

    如何使用宏来定义一个自定义函数呢? 首先我们来看下面这段代码 #define SQUARE(x) x*x int main() {int a = 5;printf("SQUARE(a): % ...

  6. define关键字的使用,以及宏函数的定义

     define关键的作用是预定义 好处是:预定义的值只要改变了,程序中只要是使用了预定义的部分就可以一改全改. 截图如下: 上面的部分程序仍然可以正常输出. 3.关于宏函数 #include< ...

  7. python展开 c函数中的宏预处理_C 语言常用的预处理-宏函数

    #include // 宏函数 三目运算符 #define MAX(A, B) A>B?A:B //宏函数 多行 添加\直接回车 #define LOOP(FROM, TO, CONTENT)\ ...

  8. c语言宏函数怎么传递宏参数_C语言中的宏参数评估

    c语言宏函数怎么传递宏参数 We can define a function like Macro, in which we can pass the arguments. When a Macro ...

  9. define定义的函数如何引用_「C与指针心得」25.预处理器-宏函数

    感谢您的阅读与点赞!欢迎关注:「大猫玩程序」,查看C语言系列文章 上一节讲了一些系统的预定义宏,这一节来讲一讲 宏定义.宏函数. 预处理常量 define: 预处理器指令从#开始,到最后第一个换行符为 ...

最新文章

  1. 天翼云从业认证(2.1)云计算的定义、特点、背景和发展历程
  2. Mysql的concat concat_ws group_concat
  3. 记一次ubuntu阿里的下载源的问题
  4. 【python】python redis的安装与使用
  5. js获取datagrid行,但是行改变了肿么办?
  6. 4.1)深度卷积网络:卷积神经网络基础
  7. 【Selenium2】【Shell】
  8. CentOS 6.5编译安装MySQL5.7.7rc
  9. PHPMailer如何获取QQ邮箱授权码
  10. android realm jar包,android-Realm支持maven或拥有jar的最新资源
  11. 如何向打游戏一样学习?(摘自大佬,如有冒犯,请多包涵)
  12. ParNew回收器和Parallel Scavenge回收器介绍
  13. 量化投资学习——股票分红对期指的影响
  14. 一台计算机多个显示,一台计算机如何有两个显示器并显示不同的内容?
  15. python9行代码_如何用9行Python代码编写一个简易神经网络
  16. Pyhton可视化(1): 历年中国大学学术排行榜
  17. 刚安装完成的Jmeter5打开之后没有工作台
  18. 我的计算机关闭不了怎么办,我的电脑怎么关不了机 该怎么办【图文】
  19. 疫苗行业发展现状:2022年猴痘疫苗产品占比提升
  20. 苹果cmsv10蓝色简洁影视电影资源采集网站模板

热门文章

  1. 大数据怎样帮助运维工程师实现无死角监控?
  2. Linux sudo命令的概念与使用
  3. 多节点 devstack 部署
  4. windows环境下VS2013编译openSSL
  5. 《小艾上班记》—— 读后总结
  6. Android与iOS/WP8跨平台整合设计与开发_专栏
  7. 有效利用番茄工作法提高效率--XorTime的使用方法
  8. Language binding(语言绑定)
  9. 闲话WPF之六(XAML的标记兼容性(Markup Compaibility))
  10. Linux 命令(54)—— trap 命令(builtin)