为什么C / C ++预处理器在这里添加空格?

我的预处理器有一个小问题困扰我,我在文档/预处理器/语言规范中找不到任何解释。

#define booboo() aaa booboo()bbb booboo().bbb 

被预处理成:

 aaa bbb <--- why is space added here aaa.bbb 

处理三字符,连续行和注释后,预处理器在预处理程序指令上工作,并将输入分为预处理标记和空格。 booboo的替换列表包含一个pp标记,它是标识符’aaa’。 booboo()bbb分为pp-tokens:’booboo’,’(’,’)’,’bbb’。 ‘booboo’,’(’,’)’的序列被识别为function宏调用,它应该扩展为’aaa’,输出中的imho应该看起来像’aaabbb’。 我说过看起来像是 – 对于人类 – 它看起来像一个标记,而编译器将获得2个令牌’aaa’和’bbb’,因为没有使用允许pp-token连接的’##’运算符。 当’booboo()。bbb’导致’aaa.bbb’没有空格时,为什么/什么规则使cpp(c预处理器)在’aaa’和’bbb’之间放置额外的空格?

这是因为cpp试图使输出(主要是针对人类)产生不连续性吗? 人类无法分辨出’aaabbb’是由2个令牌组成的,因为它只能看到令牌的拼写。 我对吗? 我已经阅读了关于预处理器的C99文档和cpp的gcc文档。 我什么也看不见。

如果我是对的,我们在这里有类似的情况:

 #define baba() + baba()+ baba()- 

结果是:

 + + +- 

否则(如果’++’是输出)它会看起来像’++’令牌,但会有2个令牌’+’和’+’。 是否与’##’运算符一样,cpp检查串联是否产生有效令牌,但是在显示的情况下想要阻止人类执行串联? ‘+ – ‘不含糊,因此没有添加空格

预处理的结果是将源文件转换为标记列表。 在您的情况下,令牌列表将在标记化后看起来像:

 .... booboo() bbb .... 

宏替换后:

 .... aaa bbb .... 

然后编译器将令牌列表转换为可执行文件。

您看到的空白只是一个实现细节,编译器等已经选择在向您显示中间结果时布置预处理标记。 标准对任何中间处理文件都没有任何说明。 不需要有单独的程序来进行预处理。

我自己在90年代早期编写了一个ANSI C编译器。 据我记忆,评论标记/ …… /应该用一个空格代替。 宏将文本替换到位。 由文本替换此类宏扩展产生的令牌不一定是合法的C语言令牌。 当宏被定义为文本’aaa’时,只是文本’aaa’进入输入流。 由于这个原因,C的解析器可能会也可能看不到有效的令牌!

因此,给出:

定义booboo()aaa

扩展booboo()bbb应该导致文本aaabbb

这个aaabbb意味着什么取决于用户。 但即使恰好是宏的名称,也不会对aaabbb进行预处理。 这是肯定的。 但是aaabbb可能是一个用户标识符 – 没有问题。