具有两个反斜杠的线如何欺骗C预处理器?

Wol*_*ram 16 c haskell c-preprocessor

我决定看一下标准Haskell模块Data.List的来源,发现一些有趣的东西.代码显然首先由C预处理器处理,作为一堆#ifdefs建议,然后才由Haskell编译器编译.但是,正如文档中所指出的,C预处理器对不同于C本身的源代码不是很友好:

C预处理器仅用于C,C++和Objective-C源代码.在过去,它被滥用为一般的文本处理器.它会阻塞不遵守C的词汇规则的输入.例如,撇号将被解释为字符常量的开头,并导致错误.此外,您不能依赖它来保留对C系列语言不重要的输入特性.如果预处理了Makefile,则将删除所有硬选项卡,并且Makefile将不起作用.

但不知何故,Haskell代码仍在C预处理下保留?可能这个片段给出了一个线索:

#ifdef __GLASGOW_HASKELL__
import GHC.Num
import GHC.Real
import GHC.List
import GHC.Base
#endif

infix 5 \\ -- comment to fool cpp

-- -----------------------------------------------------------------------------
-- List functions
Run Code Online (Sandbox Code Playgroud)

这是如何comment to fool cpp工作的?看起来像一个有趣的黑客,但我不能谷歌任何关于这个主题.在Haskell中,这一行声明了一个\\优先级为5 的中缀运算符,并--忽略了之后的所有文本.但它对C预处理器有什么作用,以及它实际上是"被欺骗"的方式?

Jea*_*bre 13

如果你简单地说:

infix 5 \\
Run Code Online (Sandbox Code Playgroud)

当行位于文件末尾时,C预处理器发出以下消息:

infix 5 \foo.c:8:10: warning: backslash-newline at end of file
Run Code Online (Sandbox Code Playgroud)

如果它不在文件的末尾(感谢@commenter),它只是"吃掉"一个反斜杠(将它与下面的换行符相关联),并且Haskell端的输出不正确:

infix 5 \
Run Code Online (Sandbox Code Playgroud)

但是如果你之后添加一个Haskell类型的注释,Haskell会忽略它(显然!),并且它不是C预处理器的问题,因为\它不在行的末尾:

infix 5 \\ -- comment
Run Code Online (Sandbox Code Playgroud)

cpp发出完全相同的文本,Haskell可以解析有趣的部分,剥离--`评论.

(请注意,它永远不会是有效的C,但预处理器并不介意)

注意:如果你想结束你的C/C++ //注释行,问题是类似的\:你不能没有继续下一行的评论:不是你想要的.