1 条件编译的基本概念
-
条件编译是宏定义和预处理器的应用
-
应用场合:开发不同档次的产品(低端/中端/高端) => 同一份代码产生不同的产品
-
条件编译的行为类似于C语言中的
if...else...
-
条件编译本质是预编译指示命令,用于控制是否编译某段代码
-
示例1:预编译指令
-
Code
#include <stdio.h> #define C 1 int main() { const char* s; #if( C == 1 ) s = "This is first printf... "; #else s = "This is second printf... "; #endif printf("%s", s); return 0; } // 输出结果 This is first printf...
-
单步编译:
gcc -E test.c -o test.i
int main() { const char* s; s = "This is first printf... "; return 0; }
-
2 条件编译的本质
-
预编译器根据条件编译指令有选择的删除代码
-
编译器不知道代码分支的存在
-
if...else...
语句在运行期进行分支判断 -
条件编译指令在预编译期进行分支判断
-
可以通过命令行定义宏:
-D
,而不用#define
来定义 -
示例2:通过命令行定义宏
#include <stdio.h> int main() { const char* s; #ifdef C s = "This is first printf... "; #else s = "This is second printf... "; #endif printf("%s", s); return 0; }
- GCC 直接编译运行结果:
This is second printf...
- 通过命令行定义宏编译:
gcc -DC=1 test.c -o test
,运行结果:This is first printf...
- GCC 直接编译运行结果:
3 #include 的本质
-
#include
的本质是将已经存在的文件内容嵌入到当前文件中 -
#include
的间接包含同样会产生嵌入文件内容的操作 -
间接包含同一个头文件会产生编译错误
-
示例3:重复包含头文件
// test.c #include <stdio.h> #include "test.h" #include "global.h" int main() { const char* s = hello_world(); int g = global; printf("%s ", NAME); printf("%d ", g); return 0; } // test.h #ifndef _TEST_H_ #define _TEST_H_ #include "global.h" const char* NAME = "test.h"; char* hello_world() { return "Hello world! "; } #endif // global.h #ifndef _GLOBAL_H_ #define _GLOBAL_H_ int global = 10; #endif
-
GCC 编译
In file included from test.c:3: global.h:2: error: redefinition of 'global' global.h:2: error: previous definition of 'global' was here
-
单步编译:
gcc -E test.c -o test.i
,可以发现因为头文件的重复包含,global
变量被重复定义了
-
-
条件编译可以解决头文件重复包含的编译错误
// test.h #ifndef _TEST_H_ #define _TEST_H_ #include "global.h" const char* NAME = "test.h"; char* hello_world() { return "Hello world! "; } #endif // global.h #ifndef _GLOBAL_H_ #define _GLOBAL_H_ int global = 10; #endif // 输出结果 test.h 10
4 条件编译的意义
-
条件编译可以按不同的条件编译不同的代码段,因而可以产生不同的目标代码
-
#if... #else...#endif
被预编译器处理,而if...else...
语句被编译器处理,必然被编译进目标代码 -
条件编译主要应用于
- 不同的产品线共用一份代码
- 区分编译产品的调试版和发布版
-
示例4:条件编译应用
- DEBUG 宏的值决定是 Debug 版本的还是 Release 的,所打印的日志不一样
- HIGH 宏的值决定是高水平的还是水平的版本,所提供的功能不一样
#include <stdio.h> #include "product.h" #if DEBUG #define LOG(s) printf("[%s:%d] %s ", __FILE__, __LINE__, s) #else #define LOG(s) NULL #endif #if HIGH void f() { printf("This is the high level product! "); } #else void f() { } #endif int main() { LOG("Enter main() ..."); f(); printf("1. Query Information. "); printf("2. Record Information. "); printf("3. Delete Information. "); #if HIGH printf("4. High Level Query. "); printf("5. Mannul Service. "); printf("6. Exit. "); #else printf("4. Exit. "); #endif LOG("Exit main() ..."); return 0; } //product.h #define DEBUG 1 #define HIGH 1