这取决于“无效的 C 或 C++ 代码”的含义。
a 内的文字comment不必遵守大多数语言规则。它甚至没有被标记化。这是完全有效的:
/* This comment doesn't contain a valid sequence of preprocessing tokens
(because of the apostrophe). */
它必须遵守的唯一规则是控制评论结束位置的规则。人们经常会被行注释中的反斜杠换行符绊倒(事实上,SO 的语法荧光笔曾经犯过这个错误!)
// Line comment with ascii art ending with a \
Oops! This line is commented out too!
并且较少使用块注释而不是嵌套(如果只是因为每个 C 教程都会警告您这一点):
/* you can't nest /* block comments */ these words are not commented */
另一方面,“跳过”预处理器条件“组”内的文本does必须遵守语言的一些规则。标准(C99 §6.10.1p5)的确切措辞是
按顺序检查每个指令的条件。如果其计算结果为假(零),则该组
它控制的内容被跳过:指令仅通过确定的名称进行处理
该指令用于跟踪嵌套条件的级别;剩下的
指令的预处理标记将被忽略,正如指令中的其他预处理标记一样。
团体。
有两个重要的部分。一、正文is标记化,所以它does必须是预处理标记的有效序列。
#if 0
This skipped conditional group doesn't contain a valid sequence of
preprocessing tokens (because of the apostrophe).
#endif
是一个语法错误。
$ gcc -fsyntax-only test.c
test.c:2:37: warning: missing terminating ' character
this skipped conditional group doesn't contain a valid sequence of
^
其次,指令仍然被部分处理“以便跟踪嵌套条件的级别”,这意味着您can做这个:
#if 0 // forget this entire mess
#ifdef __linux__
do_linux_specific_thing();
#elif defined __APPLE__
do_osx_specific_thing();
#elif defined _WIN32
do_windows_specific_thing();
#endif
#endif
and you can’t do this:
#ifdef __linux__
do_linux_specific_thing();
#elif defined __APPLE__
do_osx_specific_thing();
#if 0 // forget windows
#elif defined _WIN32
do_windows_specific_thing();
#endif
#endif
(最后你不会得到错误,但是......
$ gcc -E -P -U__linux__ -D__APPLE__ -D_WIN32 test.c
do_osx_specific_thing();
do_windows_specific_thing();
……我不认为这就是写它的人的本意。)
许多语言指南都会告诉您如何使用#if 0
“注释掉”您想要暂时禁用的大块代码区域。他们这么说是因为块注释不能嵌套。如果您尝试使用块注释禁用代码区域,但该区域内有块注释,则注释将提前结束,并且代码可能无法编译。这在 C 没有行注释的时代更为重要;一些项目仅使用行注释进行注释,保留块注释以禁用代码。
但因为里面的代码#if 0
… #endif
仍然是标记化的,并且嵌套预处理器条件仍然必须平衡,您必须小心放置的位置#if 0
和#endif
。这通常不是问题,因为代码在禁用它之前用于编译,因此其中不应该包含任何导致标记化错误的内容。