9

据我所知\,在 C 中只是附加下一行,就好像没有换行符一样。

考虑以下代码:

main(){\
return 0;
}

当我看到预处理代码(gcc -E)时,它显示

main(){return
       0;
}

并不是

main(){return 0;
}

这种行为的原因是什么?另外,我怎样才能得到我期望的代码?

4

3 回答 3

10

是的,您的预期结果是 C 和 C++ 标准所要求的结果。反斜杠只是转义换行符,即删除了反斜杠换行符序列。

我的 OS X 安装中的 GCC 4.2.1 提供了预期的结果,Clang 也是如此。此外,#define在开头添加 a 并使用

#define main(){\
return 0;
}
main()

产生正确的结果

}
{return 0;

也许gcc -E在预处理之后和输出之前做一些额外的处理。无论如何,预处理器的其余部分看到的换行符似乎在正确的位置。所以这是一个化妆品错误。

更新:根据GCC FAQ-E(或cpp命令的默认设置)尝试将输出标记放置在与输入标记大致相同的可视位置。要获得“原始”输出,请-P同时指定。这解决了观察到的问题。

大概是怎么回事:

  1. 为了保持视觉外观,未用空格分隔的标记保持在一起。
  2. 线拼接发生在为上述识别空格之前。
  3. 和标记被分组到相同的视觉块中{return
  4. 0跟在一个空格之后,并适当地注明它在下一行的位置。

PLUG:如果这对你来说真的很重要,我已经实现了我自己的预处理器,正确实现了原始预处理和保留空白的“漂亮”模式。在此讨论之后,我线拼接添加到保留的空白处。不过,它并不是真正的独立工具。它是一个编译器框架的测试平台,它恰好是一个完全兼容的 C++11 预处理器库,它恰好有一个微型命令行驱动程序。(不过,错误消息与没有颜色的 GCC 或 Clang 相当。)

于 2013-06-25T07:30:44.153 回答
10

来自K&R 第 A.12 节预处理

A.12.2 线路拼接

通过删除反斜杠和后面的换行符来折叠以反斜杠字符 \ 结尾的行。这发生在划分为令牌之前。

于 2013-06-25T06:57:28.467 回答
4

没关系:/标记器不会看到任何区别。1

更新回应评论:

对于预处理器的预期输出应该是什么,似乎存在相当多的混淆。我的观点是期望/似乎/一目了然,但实际上不需要以这种方式指定输出有效。输出中存在的空白数量与解析器无关。重要的是预处理器在解释续行时应将其视为一行。

换句话说:预处理器不是一个文本转换工具,它是一个标记操作工具。

如果这对你很重要,你可能是

  • 将预处理器用于 C/C++ 以外的其他内容
  • 将 C++ 代码视为文本,这是一种……代码味道。(想到 libclang 和各种不太完整的解析器库)。

1(预处理器可以自由地以它认为合适的任何方式实现指定的结果。您看到的结果可能是实现者发现实现此特定转换的最有效方式)

于 2013-06-25T06:54:08.047 回答