【问题标题】:Why is C/C++ preprocessor adding a space here?为什么 C/C++ 预处理器在此处添加空格?
【发布时间】:2015-06-24 08:39:04
【问题描述】:

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

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

被预处理成:

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

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

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

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

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

结果:

+ +
+-

否则(如果 '++' 是输出)它会看起来像人类的 '++' 标记,但会有 2 个标记 '+' 和 '+'。是否像 '##' 运算符一样,cpp 检查连接是否产生有效令牌,但在所示情况下希望阻止人类执行连接? '+-' 没有歧义,因此没有添加空格

【问题讨论】:

标签: c++ c c-preprocessor


【解决方案1】:

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

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

然后在宏替换之后:

....
aaa
bbb
....

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

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

【讨论】:

  • @BlueMoon 根本不需要单独的预处理器,所以它不需要做任何事情。翻译的预处理阶段只是指定为生成令牌列表,而不是生成文件。 “预处理器输出”是源文件和可执行文件之间的中间阶段。
  • @Matt:我会改写你对某事的回答(恕我直言更好):“预处理的目标是将源文件转换为标记列表,然后成为编译器的输入。在你的情况下(标记化后)标记列表看起来像这样”并且不会说 'booboo()' 是一个标记,而是 3 个标记。其余的都清晰漂亮。
  • @Blue Moon:“根本不需要单独的预处理器”与“确实不需要”处理器”不同。 Matt 说的是编译器不需要以应该呈现给我们(人类)的方式查看预处理器的输出。编译器只需要标记,不需要空格。预处理器允许输出其工作结果的功能仅供人类使用,以便我们可以调试......并且减少头疼;-)
  • @Blue Moon:“你为什么还要费心去看‘一些预处理’的输出呢?” - 变得比昨天更聪明
【解决方案2】:

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

因此,给定:

定义 booboo() aaa

扩展 booboo()bbb 应该会产生文本 aaabbb

aaabbb 是什么意思取决于用户。但是那个 aaabbb 不会被预处理,即使它恰好是一个宏的名字。这是肯定的。但 aaabbb 可能是用户标识符 - 没有问题。

【讨论】:

  • 这将连接不同的标记,这不会发生。
  • 有一个单独的指令## 用于连接标记。
猜你喜欢
  • 2021-06-16
  • 2021-06-02
  • 1970-01-01
  • 2011-01-02
  • 2011-10-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多