【问题标题】:Compilers that required # on the first column?第一列需要 # 的编译器?
【发布时间】:2017-10-16 21:21:28
【问题描述】:

是否有广泛使用的 pre-ANSI C 编译器要求# 位于第一列?

†​​ 我会接受this list 上的任何编译器。如果我能在 comp.lang.c Usenet 新闻组中 1995 年之前的帖子中找到提及它,我会接受它。

K&R C 没有指定# 之前是否允许空格。来自原始The C Programming Language,附录 A 中“C 参考手册”的§12¶1:

C 编译器包含一个能够进行宏替换、条件编译和包含命名文件的预处理器。以# 开头的行与此预处理器进行通信。

因此,未指定是否允许在 # 之前使用空格。这意味着如果指令不是从第一列开始,则 pre-ANSI 编译器可能无法编译程序。

在 ISO C(以及之前的 ANSI C)中,明确允许 C 预处理指令以空格作为前缀。在 ANSI C (C-89) 中:

预处理指令由一系列预处理组成 以# 预处理令牌开头的令牌,即 源文件中的第一个字符(可选在空格之后 不包含换行符)或后面的空格 至少包含一个换行符,并由下一个结束 换行符。

ISO C.2011 有类似的语言,但进一步澄清:

预处理指令由一系列满足 以下约束:序列中的第一个标记是# 预处理标记(在 翻译阶段 4 的开始)是源文件中的第一个字符(可选 在不包含换行符的空格之后)或在空格之后 至少包含一个换行符。序列中的最后一个标记是第一个换行符 序列中第一个标记之后的字符。165) 换行符结束 预处理指令,即使它出现在函数类宏的调用中。
165) 因此,预处理指令通常称为“行”。这些“行”没有其他句法 意义,因为除了在预处理期间的某些情况下,所有空白都是等价的(请参阅 以# 6.10.3.2 中的字符串字面量创建运算符为例)。

【问题讨论】:

  • 有人在对最近一个问题的评论中确实提到了这一点,但 MSVC 不要求 #include# 位于第一列。
  • @WeatherVane:是的,这是一个关于旧 C 编译器的问题,在 ANSI 要求预处理器允许空白位于 # 之前。
  • 在 pre-ansi C 的上下文中“广泛使用”是什么意思?
  • @rici:在问题中澄清了这一点。
  • @rici:据我回忆,在 ANSI 之前有一些非常流行的 C 编译器。当然还有最初的 Ken Thompson 的 C 编译器。 Stephen Johnson 有最初的可移植 C 编译器 (pcc)。我有一个支持 C 语言的旧 SuperPET,但我不确定它的起源。大多数 90 年代早期供应商推出的 C 编译器仍然支持 pre-ANSI C,因为大多数 C 软件源代码都是以这种风格编写的。

标签: c c-preprocessor kernighan-and-ritchie


【解决方案1】:

简短回答:是的。

我记得写过类似的东西

#if foo
    /* ... */
#else
#if bar
    /* ... */
#else
 #error "neither foo nor bar specified"
#endif
#endif

这样我曾经使用过的各种 pre-ANSI 编译器就不会抱怨“无法识别的预处理器指令'#error'”。这将与 Ritchie 为 pdp11 或 pcc (“便携式 C 编译器”,IIRC 是 80 年代左右的 Vax cc 的基础)的原始 cc 一起使用。这两个编译器——更准确地说,与这两个编译器一起使用的预处理器——肯定要求# 在第一列。 (实际上,虽然这些编译器非常不同,但它们可能都使用了基本相同的预处理器的不同变体,在那个年代,它们总是一个单独的程序。)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2017-01-18
  • 1970-01-01
  • 1970-01-01
  • 2017-12-20
  • 1970-01-01
  • 1970-01-01
  • 2011-06-29
  • 2017-10-26
相关资源
最近更新 更多