c语言里的宏(翻译)2
原文在这里
Object-like 宏
Object-like宏是一个简单的标识,在编译器会被一段代码代替。由于它看上去很像一个在代码中被使用的数据域,所以管它叫Object-like宏。最常使用该类型宏的场合是:用一个指定符号代替一个数字常量。
使用“#define”指令定义一个宏,#define之后跟一个宏名,宏名之后跟一段宏内容,编译器在预处理时会把宏名用宏内容替代。举例来说,
#define BUFFER_SIZE 1024
定义了一个名为BUFFER_SIZE的宏,BUFFER_SIZE指代的内容是数字1024。如果该#define语句之后的某处出现了BUFFER_SIZE
foo = (char*) malloc ( BUFFER_SIZE);
预处理器就能识别出BUFFER_SIZE是一个宏,并用1024代替它,在编译器看来,上面这句和下面这句是一摸一样的
foo = (char*) malloc (1024);
处于一些约定俗成的规则,宏名字一般全部大写。当所有表示宏的符号都大写时,阅读代码会变得比较容易。
宏内容在#define行的行末结束,当然,如果你一定要把一个宏定义写成多行,方法也是有的,那就是用反斜杠把回车符转义。当宏被展开时,转义过的回车会变成同一行,比如
#define NUMBERS 1, \ 2, \ 3 int x[] = { NUMBERS }; ==> int x[] = { 1, 2, 3 };
这种写法最常出现在错误信息里的行号表示。
宏定义没有强制的约束,括号并不是一定要配对,也不要求你的宏展开后就是合法的c语句。
c语言的预处理器顺序扫描代码,宏定义在你写过它之后才生效,所以,下面的代码输入到预处理器里后:
foo = X; #define X 4 bar = X;
产生这样的代码:
foo = X; bar = 4;
预处理器扩展一个宏时,宏的扩展会递归进行,直到没有符号可以代替为止。比如,
#define TABLESIZE BUFSIZE #define BUFSIZE 1024 TABLESIZE ==> BUFSIZE ==> 1024
TABLESIZE被展开为BUFSIZE,然后BUFSIZE被展开为1024.
注意BUFSIZE在TABLESIZE之后定义,所以TABLESIZE展开后就是BUFSIZE,而不会继续检查BUFSIZE是否可以展开。直到使用TABLESIZE时,预处理器看到BUFSIZE这个符号,才会继续扫描寻找BUFSIZE的内容。
如果你在代码的同一地点改变了BUFSIZE的定义,那么情况看起来会有些违反直观:
#define BUFSIZE 1020 #define TABLESIZE BUFSIZE #undef BUFSIZE #define BUFSIZE 37
TABLESIZE展开后是37,因为TABLESIZE先展开为BUFSIZE, 然后BUFSIZE展开为37。
如果一个宏展开后包含了该宏本身,不管是直接包含还是间接包含,宏展开都会立刻停止。该项规则防止了无限递归的产生。更多详情参看自包含宏。