c语言里的宏(翻译)8.1

原文在这里

预定义宏

许多Object-like宏是预定义的,你在使用它们的时候不必关心它们的定义。它们大致可被分为3类:标准,普通,系统相关。

在c++里,有第四类宏,它就是命名操作符。它们使用起来就和预定义宏一样,但你不能undefine它们。

  • 标准预定义宏
  • 普通预定义宏
  • 系统相关预定义宏
  • c++命名操作符

标准预定义宏

标准预定义宏由相关的语言标准定义,所以它们在所有(支持标准)的编译器上都是可用的。一些老版本的编译器可能不支持。这些宏都由双下划线开头。

__FILE__
 
这个宏展开后是当前源代码文件的文件名,表示成了一个c字符串。这是预处理器打开文件时的全路径,并不是"#include"里包含的或者当成参数传进来的短路径。比如说"/usr/local/include/myheader.h"就有可能是该宏展开后的字符串。
__LINE__

该宏展开成当前的行号,表示成一个int值。这个宏相当奇怪,每一行改变后它的展开值也会随着改变,但它却被叫成"预定义"宏,好像它从来不变似的。

在生成一个出错消息时,__FILE__ 和 __LINE__ 会非常有用。这条消息可以清晰的显示出错的文件和行号。比如

     fprintf (stderr, "Internal error: "
                      "negative string length "
                      "%d at %s, line %d.",
              length, __FILE__, __LINE__);
"#include"语句会改变__FILE__ 和 __LINE__ 宏的值,重定位到被包含的文件里。在文件结尾,当扫描器返回到原文件,__FILE__ 和 __LINE__ 宏又退回到原来的值( __LINE__ 宏的值会加1,因为扫描程序到了include语句的下一句)
`#line'语句会改变__LINE__,有时候也会改变__FILE__。查看行控制获取更多的信息。
C99包含了一个__FUNC__宏, GCC 已经提供了__FUNCTION__ 很长一段时间了,在C99出来的更早。这两个宏都展开成字符串,该字符串是当前函数的函数名。(两个宏间有差别,查看GCC文档)。它们两都不是宏,预处理器不可能知道当前的函数名。这个宏结合__FILE__和__LINE__会非常有用。
__DATE__

这个宏展开成一个字符串,描述预处理器运行当前的日期。字符串里包含了11个字符,看起来像这个样子"Feb 12 1996"。如果日期的小于10,用空格代替十位。

如果GCC不能确定当前日期,它会产生出一个警告,__DATE__ 宏会展开成"??? ?? ????"

__TIME__

这个宏展开成一个字符串,描述预处理器运行当前的时间。字符串中包含了8个字符,看起来像这个样子"23:59:01".

如果GCC不能确定当前时间,它会产生一个警告,__TIME__ 宏会展开成"??:??:??".

__STDC__

如果编译器符合ISO C 标准,那么该宏会展开成1.如果GCC CPP扩展在GCC以外的编译器里被使用,那么该宏不一定展开成1.  但是预处理器总是遵从c标准,除非-traditional-cpp 开关被打开。

如果-traditional-cpp开关被打开,则该宏未被定义。

在有些主机里,系统编译器遵循另一套惯例, __STDC__ 通常展开成0,在用户指定必须严格遵循c标准时展开成1.CPP在处理系统头文件时总是遵循系统惯例,但是在处理用户头文件是总是扩展为1. 这种特性会引入bug。某些版本的Solaris提供的X Window 头文件里,__STDC__ 被指定为要么没定义要么为1. 查看

__STDC_VERSION__

该宏展开成形如yyyymmL的c标准版本号,是一个long型的数值。YYYY是标准的年份,MM是标准的月份。该宏定义了编译器会遵循哪一个c标准。和__STDC__ 一样,除非GNU CPP是用在GCC里的,否则该宏也不是强制要求实现。

199409L指定了C89标准(c89标准在1994年颁布),该值是缺省值。值199901L指定了C99标准(在1999年颁布)。

如果-traditional-cpp开关被打开,则该宏未定义。

__STDC_HOSTED__

如果编译器在一个hosted环境里运行,那么该宏展开成1. hosted环境提供了c标准库需要的所有元素。

__cplusplus
 

当使用c++编译器时,该宏被定义。你可以使用__cplusplus来检测一个文件是被c编译器编译的还是被c++编译器编译的。该宏和__STDC_VERSION__ 宏一样生成一个版本号。符合1998年c++标准的编译器会把该宏展开成199711L.

__OBJC__
 
若OBJECTIVE-C编译器被使用,则该宏展开成1. 你可以宏__OBJC__ 宏检测一个文件是否正在被objective-c编译器编译。
__ASSEMBLER__

当预处理汇编语言时,该宏展开为1.

posted @ 2008-12-02 20:08  gussing  阅读(962)  评论(0编辑  收藏  举报