为什么 C/C++ 预处理器在此处添加 space?

Why is C/C++ preprocessor adding a space here?

我对预处理器有一个小问题,这让我很困惑,我在 documentation/preprocessor/language 规范中找不到任何解释。

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

预处理为:

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

处理三字母、续行和注释后,预处理器处理预处理器指令并将输入分为预处理标记和白色space。 booboo 的替换列表包含一个 pp-token,它是标识符 'aaa'。 booboo()bbb分为pp-tokens:'booboo', '(', ')', 'bbb'。 'booboo'、'('、')' 的序列被识别为功能宏调用,它应该扩展为 'aaa' 并且输出中的恕我直言应该看起来像 'aaabbb'。我说看起来像,因为 - 对人类来说 - 它看起来像一个标记,而编译器会得到 2 个标记 'aaa' 和 'bbb',因为没有使用允许 pp-token 连接的 '##' 运算符。 Why/what 规则使 cpp(c 预处理器)在 'aaa' 和 'bbb' 之间放置额外的 space 当 'booboo().bbb' 导致 'aaa.bbb' 而没有 space ?

这是因为 cpp 试图使输出(主要针对人类)明确吗?人类无法判断 'aaabbb' 是由 2 个标记组成的,因为它只能看到标记的拼写。我对吗?我已经阅读了关于预处理器的 C99 文档和 gcc 的 cpp 文档。我什么都看不到。

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

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

结果:

+ +
+-

否则(如果“++”是输出)它看起来像“++”标记,但会有 2 个标记“+”和“+”。是否与“##”运算符一样,cpp 检查串联是否产生有效令牌,但在所示情况下想要防止人类执行串联? '+-' 没有歧义,因此没有添加 space

预处理的结果是将源文件转换为标记列表。在您的情况下,标记化后的标记列表如下所示:

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

然后宏替换后:

....
aaa
bbb
....

然后编译器将标记列表翻译成可执行文件。

您看到的空白只是您的编译器等在向您显示中间结果时选择布置预处理标记的实现细节。这些标准对任何中间处理文件只字不提。也不需要单独的程序来做预处理。

我在 90 年代初自己编写了一个 ANSI C 编译器。据我所知,评论标记 /....../ 应该被单个白色-space 替换。宏就地进行文本替换。由此类宏扩展的文本替换产生的标记不一定是合法的 C 语言标记。当宏定义为文本 'aaa' 时,只有文本 'aaa' 进入输入流。因此,C 的解析器可能会也可能不会看到有效的标记!

因此,给定:

定义 booboo() aaa

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

aaabbb 的含义取决于用户。但是那个 aaabbb 即使恰好是宏的名称也不会被预处理。这是肯定的。但是 aaabbb 可能是一个用户标识符 - 没有问题。