如果我有:
#define X 5
#define Y X
预处理器中发生了什么事情? 它是通过整个文件并将每X更改为5, 然后回到下一个定义然后将每个Y更改为5(因为在上一次迭代中Y得到5)?
答案 0 :(得分:4)
C标准有一个关于如何扩展宏的特殊术语。
宏名称实际上存储在“此时定义的所有宏”的大表中。左侧的每个表项“宏名称”(以及中间的任何参数)和右侧的“扩展令牌流”。
当要扩展宏时(因为它出现在某个非预处理器行中,或者发生在必须扩展它的预处理器行中的位置 - 例如,您可以#define STDIO <stdio.h>
然后{{ 1}}),表条目是“涂成蓝色”,然后读取替换标记流(参数扩展也由标准规定)。
如果替换令牌流包含原始宏名称,则它不再匹配,因为“蓝色涂料”掩盖了名称。
当完全处理替换令牌流时,将删除“蓝色颜料”,重新公开名称。
因此:
#include STDIO
向表中添加#define X 5
:(无参数),X
。
然后:
5
添加:#define Y X
:(无参数),Y
到表格。
在文件后面的某个地方,您可能会出现令牌X
。假设以上都没有被Y
编辑(从表中删除),编译器必须首先“绘制#undef
蓝色的表条目”,并用令牌{替换标记Y
{1}}。
接下来,编译器必须“绘制Y
蓝色的表条目”,并用令牌X
替换令牌X
。
令牌X
不是预处理器宏名称(根据定义不能),因此令牌5
超出了预处理阶段的范围。现在,“{paint}”将从5
表条目中删除,就像那样;然后从5
条目中删除“蓝色油漆”,这也完成了。
如果你要改写:
X
然后,在遇到后来的令牌Y
时,序列将是:
#define Y Y, Y, Y, the letter is called Y!
蓝色Y
Y
Y
,
Y
,
Y
,
{ {1}} the
letter
is
called
被涂成蓝色,那些不匹配,Y
无法匹配,所以这些都被传递给编译器的其余部分;必须检查!
,Y
,,
和the
,但可能不在表中,因此会传递; letter
仍然涂成蓝色,因此不匹配并传递,is
无法匹配并传递。