04-记号
16.2.1 记号
从技术角度来看,可以把宏的替换体看作是记号(token)型字符串,而不是字符型字符串。C预处理器记号是宏定义的替换体中单独的“词”。用空白把这些词分开。例如:
#define FOUR 2*2
该宏定义有一个记号: 2 * 2 序列。但是,下面的宏定义中:
#define SIX 2 * 3
有3个记号: 2 、*、 3 。
替换体中有多个空格时,字符型字符串和记号型字符串的处理方式不同。考虑下面的定义:
#define EIGHT 4 * 8
如果预处理器把该替换体解释为字符型字符串,将用 4 8 替换 EIGHT 。即,额外的空格是替换体的一部分。如果预处理器把该替换体解释为记号型字符串,则用3个的记号 4 8 (分别由单个空格分隔)来替换 EIGHT 。换而言之,解释为字符型字符串,把空格视为替换体的一部分;解释为记号型字符串,把空格视为替换体中各记号的分隔符。在实际应用中,一些C编译器把宏替换体视为字符串而不是记号。在比这个例子更复杂的情况下,两者的区别才有实际意义。
顺带一提,C编译器处理记号的方式比预处理器复杂。由于编译器理解C语言的规则,所以不要求代码中用空格来分隔记号。例如,C编译器可以把 2 2 直接视为 3 个记号,因为它可以识别 2 是常量,是运算符。