带有#include 指令的尾随字符
Trailing characters with #include directive
我在源文件中有一行看似无关紧要的行
#include <some_sys_header_file.h>"
它被一堆其他使用双引号(而不是尖括号)的包含埋没了,所以没有发现虚假的双引号。
编译器(或者更确切地说,预处理器)很高兴,包含了所需的文件,并跳过了该行的其余部分。
但是,当使用 Artistic Style 格式化文件时,双引号导致文字字符串被错误地分割成多行而造成混乱。
对于如何处理这种情况是否有标准?
这是未定义的行为。
C99 在 6.10 中说#include 指令的形式为
# include pp-tokens new-line
唯一以 "
开头的 pp-tokens 是字符串文字(C99 6.4.5 字符串文字)和 header-name双引号(C99 6.4.7 Header 名称)。但是,字符串文字不得包含 un-escaped new-lines 并且 header-name 不得包含 new-lines。
单独的 "
也不能成为 header-name 的一部分,因为它不在 <>
中(C99 6.4.7 Header names) .
根据C99 6.4词法元素剩下的是
preprocessing-token:
...
each non-white-space character that cannot be one of the above
结合第 3 段中的语义
If a '
or a "
character matches the last category, the behavior is
undefined.
因此您可能会或可能不会得到诊断。
编写标准时,一些编译器没有在其 #include
参数上使用正常的 string-parsing 逻辑(尤其是 angle-bracket 形式,在其他任何地方都没有使用)。由于右尖括号后面不应跟除白色 space 以外的任何内容,因此编译器可以简单地删除最后一个 non-whitepsace 字符(应该是尖括号)而无需检查它是什么,并使用它前面的任何内容作为文件名。这个,编译器可以考虑:
#include <stdio.h> Hey
作为包含名为 stdio.h> He
的文件的请求。虽然该特定行为可能没有用,但假设可能有必要在使用 >
作为 path-separator 字符的环境中使用 C,因此可能需要:
#include <graphlib>drawing.h>
因为在预期的 header 名称之后包含字符可能会导致编译器 #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
的文件的一种方式,我认为标准可以通过考虑此类处理来适应此类事情 non-normative,要求任何实现记录此类 non-normative 行为,并且不需要 strictly-compliant 程序在这样的 non-normative 平台上工作。
我在源文件中有一行看似无关紧要的行
#include <some_sys_header_file.h>"
它被一堆其他使用双引号(而不是尖括号)的包含埋没了,所以没有发现虚假的双引号。
编译器(或者更确切地说,预处理器)很高兴,包含了所需的文件,并跳过了该行的其余部分。
但是,当使用 Artistic Style 格式化文件时,双引号导致文字字符串被错误地分割成多行而造成混乱。
对于如何处理这种情况是否有标准?
这是未定义的行为。
C99 在 6.10 中说#include 指令的形式为
# include pp-tokens new-line
唯一以 "
开头的 pp-tokens 是字符串文字(C99 6.4.5 字符串文字)和 header-name双引号(C99 6.4.7 Header 名称)。但是,字符串文字不得包含 un-escaped new-lines 并且 header-name 不得包含 new-lines。
单独的 "
也不能成为 header-name 的一部分,因为它不在 <>
中(C99 6.4.7 Header names) .
根据C99 6.4词法元素剩下的是
preprocessing-token:
...
each non-white-space character that cannot be one of the above
结合第 3 段中的语义
If a
'
or a"
character matches the last category, the behavior is undefined.
因此您可能会或可能不会得到诊断。
编写标准时,一些编译器没有在其 #include
参数上使用正常的 string-parsing 逻辑(尤其是 angle-bracket 形式,在其他任何地方都没有使用)。由于右尖括号后面不应跟除白色 space 以外的任何内容,因此编译器可以简单地删除最后一个 non-whitepsace 字符(应该是尖括号)而无需检查它是什么,并使用它前面的任何内容作为文件名。这个,编译器可以考虑:
#include <stdio.h> Hey
作为包含名为 stdio.h> He
的文件的请求。虽然该特定行为可能没有用,但假设可能有必要在使用 >
作为 path-separator 字符的环境中使用 C,因此可能需要:
#include <graphlib>drawing.h>
因为在预期的 header 名称之后包含字符可能会导致编译器 #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
的文件的一种方式,我认为标准可以通过考虑此类处理来适应此类事情 non-normative,要求任何实现记录此类 non-normative 行为,并且不需要 strictly-compliant 程序在这样的 non-normative 平台上工作。