带两个反斜杠的行如何愚弄C预处理器?

带两个反斜杠的行如何愚弄C预处理器?,c,haskell,c-preprocessor,C,Haskell,C Preprocessor,我决定研究一下标准Haskell模块的源代码,发现了一些有趣的东西。很明显,代码首先是由C预处理器处理的,正如一堆#ifdef所建议的那样,然后才由Haskell编译器编译。然而,C预处理器对不同于C本身的源代码不是很友好,正如在: C预处理器仅用于C、C++和ObjuleC源代码。在过去,它作为通用文本处理器被滥用。如果输入不符合C的词法规则,它就会阻塞。例如,撇号将被解释为字符常量的开头,并导致错误。此外,您不能依赖它来保持输入的特性,这些特性对于C族语言来说并不重要。如果对Makefil

我决定研究一下标准Haskell模块的源代码,发现了一些有趣的东西。很明显,代码首先是由C预处理器处理的,正如一堆
#ifdef
所建议的那样,然后才由Haskell编译器编译。然而,C预处理器对不同于C本身的源代码不是很友好,正如在:

C预处理器仅用于C、C++和ObjuleC源代码。在过去,它作为通用文本处理器被滥用。如果输入不符合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

这个愚弄cpp的
注释是如何工作的?看起来是一个有趣的黑客,但我不能谷歌任何关于这个主题的东西。在Haskell中,此行声明一个优先级为5的中缀运算符
\\
,而
--
之后的所有文本都将被忽略。但是它与C预处理器有什么关系?它实际上是以何种方式被“愚弄”的呢?

如果你简单地说:

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

infix 5 \foo.c:8:10: warning: backslash-newline at end of file
如果它不在文件的末尾(谢谢@commenter),它只会“吃”一个反斜杠(将其与下面的换行符关联),并且Haskell端的输出不正确:

infix 5 \
但是如果您在之后添加Haskell类型的注释,Haskell会忽略它(显然!),这对于C预处理器来说不是问题,因为
\
不在行的末尾:

infix 5 \\ -- comment
cpp发布完全相同的文本,Haskell可以解析有趣的部分,去掉--`注释

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


注意:如果你想用
\
结束你的C/C++
/
注释行,问题是类似的:你不能不在下一行继续注释:不是你想要的。

好吧,但为什么它说反斜杠换行在文件的末尾?这一行显然不是文件的结尾。@Wolfram你说得对,我的测试不完整,经过编辑。啊,明白了,它吃反斜杠,因为只有一个反斜杠是为行粘合保留的,所以要在行的结尾做一个真正的反斜杠,我们需要将其转义。但是如果反斜杠不在一行的末尾,它就不会被吃掉。我不知道,谢谢)正是!非常令人耳目一新的问题,我必须说:)这就是为什么以???结尾的C单行评论也是危险的。这是一个被简单的反斜杠\取代的三角图。你没有提到你使用了哪个命令来预处理你的文件?@Sabrina这不是“我的文件”,这是Haskell模块的官方来源。我没有对它进行预处理,也没有回答你的问题。我只是对source about.backslash-newline中的注释感兴趣。当它位于行的末尾时,它主要用于将当前行与下一行连接起来,创建一个源逻辑行。在您的示例中,他们添加了haskell注释,以防止发生这种情况。好的是,哈斯克尔的评论与C、Objo C和C++不同。这里的CPP不会将其解释为注释,而是预处理标记。在这种情况下,\\将被视为转义序列字符,而不是反斜杠换行符。