“#”字符是否必须位于 C 预处理器中一行的开头?
Does '#'-character have to be at the start of a line in the C preprocessor?
我编写 C 语言已经有一段时间了。在这段时间里,我了解到将 preprocessor-directives 之前的“#”字符放在第一列是一种常见的约定。
示例:
#include <stdio.h>
int main(void) {
#ifdef MACRO1
#ifdef MACRO2
puts("defined(MACRO1) && defined(MACRO2)");
#else
puts("defined(MACRO1)");
#endif
#else
puts("!defined(MACRO1)");
#endif
return 0;
}
当人们缩进他们的预处理器指令时,他们通常这样做:
#include <stdio.h>
int main(void) {
#ifdef MACRO1
# ifdef MACRO2
puts("defined(MACRO1) && defined(MACRO2)");
# else
puts("defined(MACRO1)");
# endif
#else
puts("!defined(MACRO1)");
#endif
return 0;
}
我不认为我见过任何人这样格式化它:
#include <stdio.h>
int main(void) {
#ifdef MACRO1
#ifdef MACRO2
puts("defined(MACRO1) && defined(MACRO2)");
#else
puts("defined(MACRO1)");
#endif
#else
puts("!defined(MACRO1)");
#endif
return 0;
}
我的问题是 C 语言标准是否要求 #
字符应该在第一列。
那么上面的第三个选项是否合法?
如果以上所有情况都是合法的,那么我想知道这是否合法。
#include <stdio.h>
int main(void) {
#ifdef MACRO
puts("defined(MACRO)");
/* Now there are other characters before the `#` */ #endif
return 0;
}
这里的 #endif
不再位于行的 "start" 上,因为中间还有其他 non-whitespace 个字符。
最后一个例子似乎很奇怪 Vim
text-editor 没有突出显示评论后面的 #endif
。
我给出的所有这些示例都使用 gcc
并打开了 -Wall -pedantic
标志进行编译,没有任何警告(包括最后一个在 #endif
之前带有注释的示例)。
请注意,我只是对语法感到好奇。当我编程时,我总是像其他人一样将 #
-character 放在第一列。我永远不会在严肃的项目中写 ++i; #endif
这样的东西。
在某些准标准 C 预处理器中(即 1989 年之前),预处理器仅识别行首的 #
。
由于 C89/C90 标准要求预处理器将 #
识别为行中的第一个非空白字符(C99 和 C11 标准也是如此),它现在是完全合法的缩进指令,在这个千年里,即使是可移植的代码也可以这样做。
在 ISO/IEC 9899:2011(C11 标准)中,第 6.10 节预处理指令说:
A preprocessing directive consists of a sequence of preprocessing tokens that satisfies the
following constraints: The first token in the sequence is a #
preprocessing token that (at
the start of translation phase 4) is either the first character in the source file (optionally
after white space containing no new-line characters) or that follows white space
containing at least one new-line character.
翻译阶段在第 5.1.1.2 节翻译阶段中定义。
The source file is decomposed into preprocessing tokens 7) and sequences of
white-space characters (including comments). A source file shall not end in a
partial preprocessing token or in a partial comment. Each comment is replaced by
one space character. New-line characters are retained. Whether each nonempty
sequence of white-space characters other than new-line is retained or replaced by
one space character is implementation-defined.
Preprocessing directives are executed, macro invocations are expanded, and
_Pragma unary operator expressions are executed. If a character sequence that
matches the syntax of a universal character name is produced by token
concatenation (6.10.3.3), the behavior is undefined. A #include
preprocessing
directive causes the named header or source file to be processed from phase 1
through phase 4, recursively. All preprocessing directives are then deleted.
偶尔,您会发现源自 1980 年代的编码标准仍然规定“#
在行首”。
我通常不缩进预处理器指令,但这样做是合法的。
不,这是 C 标准的引述(来自第 6.10 节):
A preprocessing directive consists of a sequence of preprocessing tokens that satisfies the
following constraints: The first token in the sequence is a #
preprocessing token that (at
the start of translation phase 4) is either the first character in the source file (optionally after white space containing no new-line characters) or that follows white space
containing at least one new-line character.
所以它是文件开头的 #
或 在包含至少一个换行符的空格之后 .
这意味着:
# define foo
# define bar
foo
的定义很好,因为 #
是文件中的第一个标记。 bar
的定义很好,因为 #
"follows white space containing at least one new-line character."
我编写 C 语言已经有一段时间了。在这段时间里,我了解到将 preprocessor-directives 之前的“#”字符放在第一列是一种常见的约定。
示例:
#include <stdio.h>
int main(void) {
#ifdef MACRO1
#ifdef MACRO2
puts("defined(MACRO1) && defined(MACRO2)");
#else
puts("defined(MACRO1)");
#endif
#else
puts("!defined(MACRO1)");
#endif
return 0;
}
当人们缩进他们的预处理器指令时,他们通常这样做:
#include <stdio.h>
int main(void) {
#ifdef MACRO1
# ifdef MACRO2
puts("defined(MACRO1) && defined(MACRO2)");
# else
puts("defined(MACRO1)");
# endif
#else
puts("!defined(MACRO1)");
#endif
return 0;
}
我不认为我见过任何人这样格式化它:
#include <stdio.h>
int main(void) {
#ifdef MACRO1
#ifdef MACRO2
puts("defined(MACRO1) && defined(MACRO2)");
#else
puts("defined(MACRO1)");
#endif
#else
puts("!defined(MACRO1)");
#endif
return 0;
}
我的问题是 C 语言标准是否要求 #
字符应该在第一列。
那么上面的第三个选项是否合法?
如果以上所有情况都是合法的,那么我想知道这是否合法。
#include <stdio.h>
int main(void) {
#ifdef MACRO
puts("defined(MACRO)");
/* Now there are other characters before the `#` */ #endif
return 0;
}
这里的 #endif
不再位于行的 "start" 上,因为中间还有其他 non-whitespace 个字符。
最后一个例子似乎很奇怪 Vim
text-editor 没有突出显示评论后面的 #endif
。
我给出的所有这些示例都使用 gcc
并打开了 -Wall -pedantic
标志进行编译,没有任何警告(包括最后一个在 #endif
之前带有注释的示例)。
请注意,我只是对语法感到好奇。当我编程时,我总是像其他人一样将 #
-character 放在第一列。我永远不会在严肃的项目中写 ++i; #endif
这样的东西。
在某些准标准 C 预处理器中(即 1989 年之前),预处理器仅识别行首的 #
。
由于 C89/C90 标准要求预处理器将 #
识别为行中的第一个非空白字符(C99 和 C11 标准也是如此),它现在是完全合法的缩进指令,在这个千年里,即使是可移植的代码也可以这样做。
在 ISO/IEC 9899:2011(C11 标准)中,第 6.10 节预处理指令说:
A preprocessing directive consists of a sequence of preprocessing tokens that satisfies the following constraints: The first token in the sequence is a
#
preprocessing token that (at the start of translation phase 4) is either the first character in the source file (optionally after white space containing no new-line characters) or that follows white space containing at least one new-line character.
翻译阶段在第 5.1.1.2 节翻译阶段中定义。
The source file is decomposed into preprocessing tokens 7) and sequences of white-space characters (including comments). A source file shall not end in a partial preprocessing token or in a partial comment. Each comment is replaced by one space character. New-line characters are retained. Whether each nonempty sequence of white-space characters other than new-line is retained or replaced by one space character is implementation-defined.
Preprocessing directives are executed, macro invocations are expanded, and _Pragma unary operator expressions are executed. If a character sequence that matches the syntax of a universal character name is produced by token concatenation (6.10.3.3), the behavior is undefined. A
#include
preprocessing directive causes the named header or source file to be processed from phase 1 through phase 4, recursively. All preprocessing directives are then deleted.
偶尔,您会发现源自 1980 年代的编码标准仍然规定“#
在行首”。
我通常不缩进预处理器指令,但这样做是合法的。
不,这是 C 标准的引述(来自第 6.10 节):
A preprocessing directive consists of a sequence of preprocessing tokens that satisfies the following constraints: The first token in the sequence is a
#
preprocessing token that (at the start of translation phase 4) is either the first character in the source file (optionally after white space containing no new-line characters) or that follows white space containing at least one new-line character.
所以它是文件开头的 #
或 在包含至少一个换行符的空格之后 .
这意味着:
# define foo
# define bar
foo
的定义很好,因为 #
是文件中的第一个标记。 bar
的定义很好,因为 #
"follows white space containing at least one new-line character."