#if 0 ..... #endif 块到底有啥作用?

Posted

技术标签:

【中文标题】#if 0 ..... #endif 块到底有啥作用?【英文标题】:What exactly does an #if 0 ..... #endif block do?#if 0 ..... #endif 块到底有什么作用? 【发布时间】:2011-02-20 15:04:24 【问题描述】:

C/C++

放在#if 0/#endif 块之间的代码会发生什么?

#if 0

//Code goes here

#endif

代码是否只是被跳过,因此不会被执行?

【问题讨论】:

这是一种用于注释大量代码或允许测试包含代码块的技术。如果没有此功能,则必须在每一行前加上 // 或以 /* 开始部分并以 */ 结束部分。后一种技术的问题是注释不嵌套,因此开发人员必须检查并处理开始和结束之间的任何*/ Why would somebody use an if 1 c preprocessor directive的可能重复 【参考方案1】:

它会永久删除该代码,因此编译器永远不会编译它。

如果他愿意,编码人员可以稍后更改#ifdef 以使该代码在程序中编译。

就像代码不存在一样。

【讨论】:

【参考方案2】:

它不仅没有被执行,甚至没有被编译。

#if 是一个预处理器命令,它在实际编译步骤之前被评估。该块内的代码不会出现在编译后的二进制文件中。

它通常用于暂时删除代码段,以便稍后重新打开它们。

【讨论】:

任何类型的评论都是如此。重要的区别在于嵌套。【参考方案3】:

这与注释掉块相同,但有一个重要区别:嵌套不是问题。考虑这段代码:

foo();
bar(x, y); /* x must not be NULL */
baz();

如果我想把它注释掉,我可以试试:

/*
foo();
bar(x, y); /* x must not be NULL */
baz();
*/

Bzzt。语法错误!为什么?因为块 cmets 不嵌套,因此(从 SO 的语法突出显示中可以看出)单词“NULL”之后的 */ 终止注释,使得 baz 调用未被注释掉,@ 之后的 */ 987654326@ 语法错误。另一方面:

#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif

用于注释掉整个事情。 #if 0s 会互相嵌套,像这样:

#if 0
pre_foo();
#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif
quux();
#endif

当然,如果没有正确注释,这可能会有点混乱,并且会成为维护方面的难题。

【讨论】:

请注意,#if 中的代码必须在词法上正确(相对于 cmets)并且预处理器指令仍然有效(同上)。 @David:它在词法上不正确,但它仍然可以编译。所以代码不必在词法上是正确的。 @Dennis,我从 gcc 收到 foo.c:3: unterminated string or character constant,你在用什么?【参考方案4】:

当预处理器看到#if 时,它会检查下一个标记是否具有非零值。如果是这样,它将为编译器保留代码。如果没有,它会删除该代码,因此编译器永远不会看到它。

如果有人说#if 0,他们实际上是在注释掉代码,因此它永远不会被编译。你可以认为这就像他们在它周围放置了 /* ... */ 一样。不太一样,但是效果是一样的。

如果您想详细了解发生了什么,您可以经常查看。许多编译器允许您在预处理器运行后查看文件。例如,在 Visual C++ 上,switch /P 命令将执行预处理器并将结果放入 .i 文件中。

【讨论】:

不完全。预处理器按行而不是按标记进行解析。根据您的解释,无法说例如#if WIN32 || __CYGWIN__ 但这确实按预期工作。 我在简化。如果有或,它将检查任何一个标记是否非零。同样,如果有,它会检查两者是否非零。【参考方案5】:

# 开头的行是preprocessor directives。 #if 0 [...] #endif 块不会进入编译器并且不会生成任何机器代码。

您可以使用源文件ifdef.cxx 演示预处理器会发生什么:

#if 0
This code will not be compiled
#else
int i = 0;
#endif

运行 gcc -E ifdef.cxx 将显示编译的内容。

您可以选择使用此机制来防止在开发周期中编译代码块,但您可能不想将其签入源代码管理,因为它只会给代码添加杂乱无章并降低可读性。如果是一段历史代码被注释掉了,那么应该去掉:源代码管理包含历史,对吧?

此外,CC++ 的答案可能相同,但没有称为 C/C++ 的语言,因此引用此类语言不是一个好习惯语言。

【讨论】:

将 C/C++ 称为“C 或 C++”的简写有什么问题?你真的认为有人会误以为有一种语言叫做“C/C++”吗? @Chris:人们经常问诸如“我如何在 C/C++ 中做 X?”之类的问题。这是一个荒谬的问题;您正在使用其中一个进行编码,如果您还没有选择,那么您应该明确说明这一点。所以,是的,人们对存在一种叫做“C/C++”的语言感到困惑 多么荒谬的说法!有成千上万个问题的答案与 C 和 C++ 相关。请记住,这是一个提问的网站。仅仅因为您问的是一般性问题并不意味着您不知道您使用的是什么语言。如果您怀疑是这种情况,就像在这个问题中一样,那么指定 C 或 C++ 有什么帮助?你认为如果每个可能适用于 C 或 C++ 的问题都被问两次会有帮助吗? @Christopher:你说得对,有很多问题的答案与 C、C++ 和 Objective-C(这就是其中之一)同样相关。 Stack Overflow 有一个方便的标记系统来表示问题所属的语言。正如@Dennis 提到的那样,SO(和其他编程论坛 [fora?])有(太多)人对 C 和其他 C 派生语言之间的划分感到困惑,他们将这些语言互换地称为 C/C++更难用适当的语言回答问题。【参考方案6】:

不完全

int main(void)

   #if 0
     the apostrophe ' causes a warning
   #endif
   return 0;

它显示“t.c:4:19: 警告:缺少终止 ' 字符” 使用 gcc 4.2.4

【讨论】:

此警告由预处理器生成,而不是编译器。编译器只能看到: # 1 "t.c" # 1 "" # 1 "" # 1 "t.c" int main(void) return 0; 【参考方案7】:

这是一种廉价的注释方式,但我怀疑它可能具有调试潜力。例如,假设您有一个将值输出到文件的构建。您可能不希望在最终版本中使用它,因此您可以使用 #if 0... #endif。

另外,我怀疑出于调试目的更好的方法是:

#ifdef DEBUG
// output to file
#endif

你可以做这样的事情,它可能更有意义,你所要做的就是定义 DEBUG 来查看结果。

【讨论】:

【参考方案8】:

我想补充一下#else 案例:

#if 0
   /* Code here will NOT be complied. */
#else
   /* Code will be compiled. */
#endif


#if 1
   /* Code will be complied. */
#else
   /* Code will NOT be compiled. */
#endif

【讨论】:

以上是关于#if 0 ..... #endif 块到底有啥作用?的主要内容,如果未能解决你的问题,请参考以下文章

Django:无效的块标签:'static',预期的'endif'

#if 0 #endif 调试方法

C 语言中#if 0

两个“IF”块之间的区别

在 Emacs 的 C/C++ 模式下,将 #if 0...#endif 块中的代码面更改为注释面

IE的if条件Hack(兼容性)