目录
一、基本概念二、条件编译的本质三、#include 的本质四、条件编译的意义五、小结一、基本概念
条件编译的行为类似于 C 语言中的 if...else...编译是预编译指示命令,用于控制是否编译某段代码下面看一段简单的条件编译的代码:
#include#define C 1 int main() { const char* s; #if( C == 1 ) s = "This is first printf...\n"; #else s = "This is second printf...\n"; #endif printf("%s", s); return 0; }
下面为输出结果:
可以输入gcc -E Test.c -o file.i 命令,看看预编译阶段发生了什么,下面是部分输出结果:
# 2 "Test.c" 2 int main() { const char* s; s = "This is first printf...\n"; printf("%s", s); return 0; }
可以看到宏定义和条件编译都没有了,由相应内容取而代之。
二、条件编译的本质
预编译器根据条件编译指令有选择的删除代码
编译器不知道代码分支的存在
if...else... 语句在运行期进行分支判断
条件编译指令在预编译期进行分支判断
可以通过命令行定义宏
gcc -Dmacro=value file.cgcc -Dmacro file.c下面看一个通过命令行定义宏的代码:
#includeint main() { const char* s; #ifdef C s = "This is first printf...\n"; #else s = "This is second printf...\n"; #endif printf("%s", s); return 0; }
终端输入gcc -DC Test.c,输出结果如下:
三、#include 的本质
#include 的本质是将已经存在的文件内容嵌入到当前文件中#include 的间接包含同样会产生嵌入文件内容的操作这就出现一个问题,间接包含同一个头文件是否会产生编译错误?
下面就来通过一段代码深入探究:
global.h:
// global.h int global = 10;
test.h:
// test.h #include "global.h" const char* NAME = "test.h"; char* hello_world() { return "hello world!\n"; }
test.c:
#include#include "test.h" #include "global.h" int main() { const char* s = hello_world(); int g = global; printf("%s\n", NAME); printf("%d\n", g); return 0; }
编译后编译器报错,global 重定义:
为什么 global 会重定义呢?下面开始单步编译,输入gcc -E test.c -o test.i,输出部分结果如下:
# 2 "test.c" 2 # 1 "test.h" 1 # 1 "global.h" 1 int global = 10; # 4 "test.h" 2 const char* NAME = "test.h"; char* hello_world() { return "hello world!\n"; } # 3 "test.c" 2 # 1 "global.h" 1 int global = 10; # 4 "test.c" 2 int main() { const char* s = hello_world(); int g = global; printf("%s\n", NAME); printf("%d\n", g); return 0; }
这样就很明显了,程序先将 test.h 里面的东西复制进 test.c,由于 test.h 里面有一个 include "global.h",就把int global = 10; 复制过来,然后复制
const char* NAME = "test.h";
char* hello_world()
{undefined
return "hello world!\n";
}
在然后由于test.c 里面又定义一个#include "global.h",又把int global = 10; 复制过来,造成了重复定义。
条件编译可以解决头文件重复包含的编译错误
#ifndef _HEADER_FILE_H_ #define _HEADER_FILE_H_ //source code #endif
如果没有定义 header_file.h,则定义,且执行里面的代码;否则,如果定义了,里面的代码就不会执行。
所以上述代码中可以这么改:
global.h:
// global.h #ifndef _GLOBAL_H_ #define _GLOBAL_H_ int global = 10; #endif
test.h:
// test.h #ifndef _TEST_H_ #define _TEST_H_ #include "global.h" const char* NAME = "test.h"; char* hello_world() { return "hello world!\n"; } #endif
这样编译就能通过了
四、条件编译的意义
条件编译使得我们可以按不同的条件编译不同的代码段,因而可以产生不同的目标代码
#if...#else...#endif 被预编译器处理,而 if...else... 语句被编译器处理,必然被编译进目标代码
实际工程中条件编译主要用于以下两种情况:
不同的产品线共用一份代码区分编译产品的调试版和发布版下面看一段产品线区分及调试代码:
product.h:
#define DEBUG 1 #define HIGH 1
test.c:
#include#include "product.h" #if DEBUG #define LOG(s) printf("[%s:%d] %s\n", __FILE__, __LINE__, s) #else #define LOG(s) NULL #endif #if HIGH void f() { printf("This is the high level product!\n"); } #else void f() { } #endif int main() { LOG("Enter main() ..."); f(); printf("1. Query Information.\n"); printf("2. Record Information.\n"); printf("3. Delete Information.\n"); #if HIGH printf("4. High Level Query.\n"); printf("5. Mannul Service.\n"); printf("6. Exit.\n"); #else printf("4. Exit.\n"); #endif LOG("Exit main() ..."); return 0; }
宏 DEBUG 是指产品是调试版还是发布版,调试版为 1,发布版为 0, 宏 HIGH指的是产品是高端产品还是低端产品,高端产品为 1,低端产品为 0
如果我们想测试调试版的高端产品,令 DEBUG 为 1,HIGH为 0 即可:
同理,我们想测试发布版的低端产品,令 DEBUG 为 0,HIGH为 0 即可:
五、小结
通过编译器命令行能够定义预处理器使用的宏条件编译可以避免重复包含头同一个头文件条件编译是在I程开发中可以区别不同产品线的代码条件编译可以定义产品的发布版和调试版到此这篇关于C语言 深入讲解条件编译的用处的文章就介绍到这了,更多相关C语言 条件编译内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
X 关闭
X 关闭
- 15G资费不大降!三大运营商谁提供的5G网速最快?中国信通院给出答案
- 2联想拯救者Y70发布最新预告:售价2970元起 迄今最便宜的骁龙8+旗舰
- 3亚马逊开始大规模推广掌纹支付技术 顾客可使用“挥手付”结账
- 4现代和起亚上半年出口20万辆新能源汽车同比增长30.6%
- 5如何让居民5分钟使用到各种设施?沙特“线性城市”来了
- 6AMD实现连续8个季度的增长 季度营收首次突破60亿美元利润更是翻倍
- 7转转集团发布2022年二季度手机行情报告:二手市场“飘香”
- 8充电宝100Wh等于多少毫安?铁路旅客禁止、限制携带和托运物品目录
- 9好消息!京东与腾讯续签三年战略合作协议 加强技术创新与供应链服务
- 10名创优品拟通过香港IPO全球发售4100万股 全球发售所得款项有什么用处?