#define中的#define;预处理器中会发生什么?

时间:2013-12-08 21:22:20

标签: c-preprocessor preprocessor-directive

如果我有:

#define X 5
#define Y X

预处理器中发生了什么事情? 它是通过整个文件并将每X更改为5, 然后回到下一个定义然后将每个Y更改为5(因为在上一次迭代中Y得到5)?

1 个答案:

答案 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时,序列将是:

  1. #define Y Y, Y, Y, the letter is called Y! 蓝色
  2. 的绘画条目
  3. 删除替换令牌序列:Y Y Y , Y , Y , { {1}} the letter is
  4. 检查表中的每个替换标记 - 因为called被涂成蓝色,那些不匹配,Y无法匹配,所以这些都被传递给编译器的其余部分;必须检查!Y,the,但可能不在表中,因此会传递; letter仍然涂成蓝色,因此不匹配并传递,is无法匹配并传递。
  5. 删除蓝色涂料,恢复展开