【问题标题】:Trailing characters with #include directive带有#include 指令的尾随字符
【发布时间】:2015-11-07 15:25:15
【问题描述】:

我在源文件中有一个看似无害的行

#include <some_sys_header_file.h>"

它被一堆使用双引号(而不是尖括号)的其他包含所掩埋,因此没有发现虚假的双引号。

编译器(或者更确切地说,预处理器)很高兴,包含了所需的文件,并跳过了该行的其余部分。

但是,当使用Artistic Style 格式化文件时,双引号会导致文字字符串被错误地拆分为多行而造成混乱。

是否有处理这种情况的标准?

【问题讨论】:

  • 你能给我们这个源文件编译/疲劳的环境吗?
  • gcc 在这种情况下可能会发出一两个警告。
  • @SantoshA:Embarcadero C++Builder 2010,a:old, b:wilfully 不符合标准。但我更感兴趣的是根据标准应该发生什么。
  • 这可能是related to this extension,因为某些系统在包含后使用了额外的字符。

标签: c language-lawyer c-preprocessor code-formatting


【解决方案1】:

这是未定义的行为

C99 在 6.10 中说 #include 指令具有以下形式

# include pp-tokens new-line

唯一以" 开头的 pp-token 是字符串文字(C99 6.4.5 字符串文字)和双引号中的标头名称(C99 6.4.7 标头名称)。但是,字符串文字不得包含未转义的换行符,标题名称不得包含换行符。 单独的 " 也不能是标题名称的一部分,因为它不在 &lt;&gt; 中(C99 6.4.7 标题名称)。 根据 C99 6.4 词法元素剩下的是

预处理令牌
...
每个不能是上述之一的非空白字符

结合第 3 段中的 语义

如果'" 字符匹配最后一个类别,则行为是 未定义。

所以您可能会或可能不会得到诊断。

【讨论】:

    【解决方案2】:

    在编写标准时,一些编译器没有在其#include 参数上使用正常的字符串解析逻辑(尤其是在其他任何地方都没有使用的尖括号形式)。由于右尖括号后面不应该跟空格以外的任何内容,编译器只需删除最后一个非空白字符(应该是尖括号)而不检查它是什么是合法的,并且使用它前面的任何内容作为文件名。这一点,编译器可以考虑:

    #include <stdio.h> Hey
    

    作为包含名为stdio.h&gt; He 的文件的请求。虽然该特定行为可能没有用,但假设有必要在使用 &gt; 作为路径分隔符的环境中使用 C,因此可能需要:

    #include <graphlib>drawing.h>
    

    由于在预期的标头名称之后包含字符可能会导致编译器#include 不是预期的文件,并且由于这样的文件可以做任何事情,因此包含标准定义之外的指令被视为未定义行为.就个人而言,我认为如果将额外的形式标准化,该语言将受益匪浅:

    #include "literal1" "literal2" ["literal3", etc.]
    

    以通常的方式应用字符串连接。我参与过的许多项目都有长得离谱的包含路径列表,如果可以说:

    #include "fooproject_directories.h"
    #include ACMEDIR "acme.h"
    #include IOSYSDIR "io.h"
    

    等等。从而明确哪些文件应该从哪里加载。尽管某处的某些代码可能依赖于以下能力:

    #include "this"file.h"
    

    作为加载名为this"file.h 的文件的一种方式,我认为标准可以通过将此类处理视为非规范性来适应此类事情,要求任何实现都记录此类非规范性行为,并且不需要严格兼容的程序在此类非规范平台上工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-24
      • 1970-01-01
      • 2017-09-03
      • 2016-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多