C预处理器-19(常见预定义宏)

3.7.2 常见预定义宏

常见的预定义宏是GNU C的扩展。无论您是在哪种机器或操作系统上使用GNU C或GNU Fortran,它们都具有相同的含义。它们的名字都以双下划线开头。

  • __COUNTER__

这个宏展开为从0开始的连续整数值。与##操作符结合使用,可以提供一种生成唯一标识符的便捷方法。需要注意确保在包含可能使用__COUNTER__的预编译头之前不要提前展开它。否则,预编译头将不会被使用。

  • __GFORTRAN__

GNU Fortran编译器定义了这个宏。

  • __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__

所有使用C预处理器的GNU编译器(包括C、C++、Objective-C和Fortran)都会定义这些宏。它们的值分别是编译器的主要版本号、次要版本号和修订版本号,作为整数常量。例如,GCC版本x.y.z会将__GNUC__定义为x,__GNUC_MINOR__定义为y,__GNUC_PATCHLEVEL__定义为z。如果直接调用预处理器,这些宏也会被定义。

如果你只需要知道你的程序是否由GCC编译,或者由声称接受GNU C方言的非GCC编译器编译,你可以简单地测试__GNUC__。如果你需要编写依赖于特定版本的代码,则需要更加谨慎。每次次版本号增加时,修订版本会被重置为零;每次主版本号增加时,次版本号和修订版本都被重置。如果你想在条件语句中直接使用预定义的宏,你需要这样写:

/* 测试GCC > 3.2.0 */
#if __GNUC__ > 3 || \
    (__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \
                       (__GNUC_MINOR__ == 2 && \
                        __GNUC_PATCHLEVEL__ > 0)))

另一种方法是使用预定义的宏计算一个数字,然后对比阈值:

#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
...
/* 测试GCC > 3.2.0 */
#if GCC_VERSION > 30200

许多人发现这种形式更容易理解。

  • __GNUG__

GNU C++编译器定义了这个宏。测试它等同于测试(__GNUC__ && __cplusplus)。

  • __STRICT_ANSI__

当GCC被调用时,如果指定了-ansi开关,或指定了严格符合某个ISO C或ISO C++版本的-std开关,则GCC定义此宏,并将其定义为‘1’。此宏主要目的是指导GNU libc的头文件仅使用标准C中的定义。

  • __BASE_FILE__

这个宏展开为主输入文件的名称,形式为C字符串常量。这是在预处理器或C编译器命令行上指定的源文件。

  • __FILE_NAME__

这个宏展开为当前输入文件的基本名称,形式为C字符串常量。这是预处理器打开文件时使用的路径的最后一部分。例如,处理"/usr/local/include/myheader.h"会将此宏设置为"myheader.h"。

  • __INCLUDE_LEVEL__

这个宏展开为代表包含文件嵌套深度的十进制整数常量。每当遇到‘#include’指令时,该宏的值加一;每当你离开一个包含文件时,其值减一。它从0开始,在命令行指定的基础文件中。

  • __ELF__

如果目标使用ELF对象格式,则定义此宏。

  • __VERSION__

这个宏展开为描述正在使用的编译器版本的字符串常量。你不应该依赖它的内容具有任何特定的形式,但它至少会包含发行编号。

  • __OPTIMIZE__ __OPTIMIZE_SIZE__ __NO_INLINE__

这些宏描述了编译模式:

  • __OPTIMIZE__ 在所有优化编译中定义此宏。
  • __OPTIMIZE_SIZE__ 如果编译器正在针对代码大小而非速度进行优化,则定义此宏。
  • __NO_INLINE__ 如果没有函数会被内联到它们的调用者(当不进行优化,或者通过 -fno-inline 特别禁用了内联时),则定义此宏。

这些宏使得某些GNU头文件能够使用宏或内联函数提供系统库函数的优化定义。除非你确保程序在这些宏被定义与否的情况下执行效果相同,否则你不应该以任何方式使用这些宏。如果它们被定义了,它们的值为1。

  • __GNUC_GNU_INLINE__

如果声明为 inline 的函数将按照GCC传统的 gnu90 模式处理,则GCC定义这个宏。目标文件将包含所有声明为 inline 而没有 extern 或 static 修饰符的函数的外部可见定义。它不会包含任何声明为 extern inline 的函数的定义。

  • __GNUC_STDC_INLINE__

如果声明为 inline 的函数将根据 ISO C99 或更新的标准处理,则GCC定义这个宏。目标文件将包含所有声明为 extern inline 的函数的外部可见定义。它不会包含任何声明为 inline 而没有 extern 修饰符的函数的定义。

如果定义了这个宏,GCC 支持使用 gnu_inline 函数属性,以此来始终实现 gnu90 模式的行为。

__CHAR_UNSIGNED__

当且仅当目标机器上的 char 数据类型为无符号类型时,GCC 会定义这个宏。它的存在是为了让标准头文件 limits.h 能正常工作。你不应直接使用这个宏,而应参考 limits.h 里定义的标准宏。

__WCHAR_UNSIGNED__

类似于 __CHAR_UNSIGNED__,此宏仅在数据类型 wchar_t 是无符号类型且前端处于 C++ 模式时定义。


__REGISTER_PREFIX__

此宏展开为一个单一的标记(不是字符串常量),表示目标平台汇编语言中用于 CPU 寄存器名称的前缀。你可以使用它编写适用于多种环境的汇编代码。例如:

  • 在 m68k-aout 环境中,它展开为空。
  • 在 m68k-coff 环境中,它展开为单个字符 %

__USER_LABEL_PREFIX__

此宏展开为一个单一的标记,表示在汇编中应用于用户标签(对 C 代码可见的符号)的前缀。例如:

  • 在 m68k-aout 环境中,它展开为 _
  • 在 m68k-coff 环境中,它展开为空。

即使使用了 -f(no-)underscores 选项,此宏仍然会有正确的定义;但如果使用了调整此前缀的目标特定选项(例如 OSF/rose 的 -mno-underscores 选项),它的值可能不正确。

__SIZE_TYPE__

__PTRDIFF_TYPE__

__WCHAR_TYPE__

__WINT_TYPE__

__INTMAX_TYPE__

<

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值