这是指启用或禁用条件编译。它讨论了使用整数表达式和预处理器宏。
假设您希望仅在调试时启用某些代码。你可以这样做:
#define DEBUGGING 1
#if DEBUGGING
printf( "I'm debugging\n" );
#endif
void function( void ) {
if ( DEBUGGING ) {
printf( "I'm debugging\n" );
}
}
该代码将起作用,即您将得到两个打印的输出语句,即“我正在调试”。
原因是因为在第一个块 ( #if DEBUGGING
) 中,宏DEBUGGING
被转换为 1(它被定义为表示的值),然后它被评估为整数表达式。换句话说,预处理器将代码简化为:
#if 1
printf( "I'm debugging\n" );
#endif
void function( void ) {
if ( 1 ) {
printf( "I'm debugging\n" );
}
}
但是现在考虑根本#DEBUGGING
没有定义宏的情况。
在这种情况下,预处理器会将代码简化为:
//#define DEBUGGING 1 <-- commented out
#if 0 // <--- DEBUGGING is not a macro-word here, so it is converted to 0
printf( "I'm debugging\n" );
#endif
void function( void ) {
if ( DEBUGGING ) { // <---- look what happened here! *Not* in "#if", so NOT preprocessed to zero!
printf( "I'm debugging\n" );
}
}
由于 C 语言的定义方式,#if
测试会将它不能识别为宏的任何单词(例如 int、sizeof、myVariableName、SOME_OTHER_UNDEFINED_THING)减少为 0,并且不会给出错误。第一个 printf 语句不会被编译。
但是,由于不再定义宏,因此使用先前版本代码中的宏的第二条语句将不会DEBUGGING
被替换。在这种情况下,在预处理器运行之后,编译器将抱怨它无法识别的名称,因为它会从字面上看到这个词DEBUGGING
并且不知道如何理解它(它不是变量名或关键字等) .
这是你引用的段落的第一件事。
它提到的第二件事是#if
语句会将其参数简化为单个整数表达式的结果。这意味着您可以编译如下所示的代码:
#define VERSION 2
#if VERSION > 1
printf( "this code only runs on v2+\n" );
#endif
预处理器首先将单词 VERSION 替换为它所代表的东西:
#if 2 > 1
...
然后预处理器将该行计算为整数表达式。由于 2 大于 1(真),因此表达式/行简化为:
#if 1
printf( "this code only runs on v2+\n" );
#endif
关于sizeof
(以及任何其他关键字或非宏词),在#if
语句中,预处理器无法识别的所有名称都将转换为零。这样它就可以处理不存在的宏的条件编译,如上面我注释掉时所示DEBUGGING
。
因此,这段代码看起来像是您可能想要做的事情:
#if sizeof(int) > 2
printf( "This machine has 4+ byte integers\n" );
#endif
将减少到这个:
#if 0(0) > 2 // sizeof and int are non-macro-words so they get replaced with 0
这是一个无效的表达式,所以编译器会报错。因此,您不能sizeof
在预处理器宏中使用(或任何其他关键字或变量名)。
如果您通过将 C 预处理器与 C 编译器分开来考虑它,这是有道理的。预处理器不知道常规的 C 关键字,这不是它的工作。它只是解析它关心的标记(#if
等),然后将后处理的 C 文件交给编译器。