gcc中预定义的宏__GNUC__gnu编译器
今天在看Linux系统编程这本书的代码的时候看到了__GNUC__,不太清楚这个宏所以去查了⼀下,以此记录。GNU C预定义了⼀系列的宏,这些宏都是以双下划线开始的,这⾥只讲⼀下__GNUC__  __GNUC_MINOR__ __GNUC_PATCHLEVEL__,其他GNU C的预定义宏可以到这⾥查看:
__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
return0;
}
预编译以后的⽂件函数部分:
# 942"/usr/include/stdio.h"34
# 2"test.c"2
int main()
{
printf("__GNUC__ = %d\n",4);
printf("__GNUC_MINOR__ = %d\n",9);
printf("__GNUC_PATCHLEVEL__ = %d\n",2);
return0;
}
这样就很直观地看到,__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
return0;
}
好啦,对__GNUC__这个预定义的宏变量算是有了⼀个基本的了解,作⽤是⽤来针对特定版本的gcc进⾏编写代码,⾄于其他预定义的宏呢可以去本⽂刚开始的时候给出的⽹站上查看,他们各⾃的作⽤也都写的⾮常清楚。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。