先说“#if 0/#if 1 ... #endif”的作用。
我们知道,C标准不提供C++里的“//.....”这样的单行风格注释而只提供“/*....*/”这样的块注释功能。
通常使用“/*.......*/”写代码中说明性的注释文字(注释作用)以及在调试时关闭某段代码对编译器的可见性(屏蔽作用),
当然,这里所谓的“注释作用”和“屏蔽作用”是我们从功能上下的主观定义,对预处理器而言,两者并无任何区别。
对于前者,因为“注释”中不会再出现“注释”和“需要屏蔽的代码段”,所以不会有嵌套的需求,因此通常也不会有问题;
而对于后者,当我们在调试程序时需要“屏蔽”某段代码时,该段代码中可能包含着前述的“注释”和/或“已被屏蔽的代码段”,这时就产生了“/*......*/”嵌套使用的需求,
但SB的C标准恰恰不允许我们这么干。
当你试图使用嵌套的块注释功能时,会发现预处理器把最外层注释的开始和最内层注释的结尾这两者之间的内容处理成了注释,而其后一直到最外层注释结尾的内容被当作了“有效代码”
举例代码如下:
1 /*
2 int Add(int a,int b)
3 {
4 return a+b;
5 }
6 /*这个函数不再使用
7 int Sum(int a,int b)
8 {
9 return a+b;
10 }
11 */
12 int Add2(int a,int b)
13 {
14 return a+b;
15 }
16 */
——这显然会引起若干语法错误而导致编译中止。
高手们开动脑筋想到了“#if 0 ... #endif”,它同样由预处理器进行处理,同样可以“屏蔽”一段代码,你想把说明文字写在里面也可以,这些和“/*........*/”一样。
1 #if (0)
2 int Add(int a,int b)
3 {
4 return a+b;
5 }
6 /*这个函数不再使用
7 int Sum(int a,int b)
8 {
9 return a+b;
10 }
11 */
12 int Add2(int a,int b)
13 {
14 return a+b;
15 }
16 #endif
但不一样的是:第一它允许嵌套(层数上限由预处理器决定)、第二你随时可以把“#if 0”改成“#if 1”来取消对某段代码的“屏蔽”——很卓越的特性,快抛弃笨拙的“”吧!
它唯一的缺点就是在编辑器中没有“注释”该有的文本显示样式。
详细拓展
当注释掉大块代码时,使用"#if 0"比使用"/**/"要好,因为用"/**/"做大段的注释要防止被注释掉的代码中有嵌套的"/**/",这会导致注释掉的代码区域不是你想要的范围, 当被注释掉的代码很大时容易出现这种情况,特别是过一段时间后又修改该处代码时更是如此。
在这里顺便对条件编译(#ifdef, #else, #endif, #if等)进行说明。以下分3种情况:
情况1:
#ifdef _XXXX
...程序段1...
#else
...程序段2...
#endif
这表明如果标识符_XXXX已被#define命令定义过则对程序段1进行编译;否则对程序段2进行编译。
例:
#define NUM
.............
.............
.............
#ifdef NUM
printf("之前NUM有过定义啦!:) \n");
#else
printf("之前NUM没有过定义!:( \n");
#endif
}
如果程序开头有#define NUM这行,即NUM有定义,碰到下面#ifdef NUM的时候,当然执行第一个printf。否则第二个printf将被执行。
我认为,用这种,可以很方便的开启/关闭整个程序的某项特定功能。
情况2:
#ifndef _XXXX
...程序段1...
#else
...程序段2...
#endif
这里使用了#ifndef,表示的是if not def。当然是和#ifdef相反的状况(如果没有定义了标识符_XXXX,那么执行程序段1,否则执行程序段2)。例子就不举了。
情况3:
#if 常量
...程序段1...
#else
...程序段2...
#endif
这里表示,如果常量为真(非0,随便什么数字,只要不是0),
就执行程序段1,否则执行程序段2。
如果有#if需要顶格写