C语言中的条件编译
通常情况,我们想让程序选择性地执行,多会使用分支语句,比如if-else 或者switch-case 等。但有些时候,可能在程序的运行过程中,某个分支根本不会执行。
比如我们要写一个跨平台项目,要求项目既能在Windows下运行,也能在Linux下运行。这个时候,如果我们使用if-else,如下:
Windows 有专有的宏_WIN32,Linux 有专有的宏__linux__
if(_WIN32)
printf("Windows下执行的代码\n");
else if(__linux__)
printf("Linux下执行的代码\n");
else
printf("未知平台不能运行!\n");
这段代码存在两个问题:1、 在Windows下并没有定义__linux__,编译的时候会报错,同样在Linux中也没有定义_WIN32。2、 假定这段程序可以运行,那么在Windows环境下另外两个分支的代码根本不可能运行,同理在Linux下也一样。
处理这种情况我们可以使用条件编译。条件编译,顾名思义,就是根据一定的条件进行选择性的编译,我们要达到的效果,就是在Windows环境下另外两个分支的语句根本不会编译,这样生成的可执行文件中,也不会还有对应语句的机器码,这样既提高了编译效率,同时也减小了可执行文件的体积。
条件编译通常可以用三种方式实现:
1、 #if--#elif--#else--#endif语句实现
通过这种方法实现的代码为:
#if(_WIN32)
printf("Windows下执行的代码\n");
#elif (__linux__)
printf("Linux下执行的代码\n");
#else
printf("未知平台不能运行!\n");
#endif
使用这种方式时需要注意,宏定义为真实#if才会执行,也就是说:
假如有宏定义#define _WIN32 0 这个时候#if是不会执行的。需要定义为#define _WIN32 1才会执行
2、 通过#ifdef--#else--#endif语句实现
通过这种方式实现的代码为
#ifdef(_WIN32)
printf("Windows下执行的代码\n");
#else
printf("Linux下执行的代码\n");
#endif
这种方法下只需要定义了_WIN32就可以,没有必要为真,也就是说
如果有宏定义#define _WIN32 0 上面#ifdef语句也是可以执行的,甚至#define _WIN32 上面的#ifdef也可以运行
当然也可以加入第一种方法中的#elif语句
#ifdef(_WIN32)
printf("Windows下执行的代码\n");
#elif (__linux__)
printf("Linux下执行的代码\n");
#else
printf("未知平台不能运行!\n");
#end
但是需要注意的是,这种情况下,要想#elif语句执行__linux__的值必须为真!(同时没有定义_WIN32)
3、 使用#ifndef语句,这种情况类似第二种,ifndef就是如果没有定义宏,就执行。
在gcc编译工具中
我们可以使用-D选项,动态地定义程序所需要的宏
比如我们可以这样编译 gcc test.c -o test -D _WIN32 这样程序就可以在Windows下运行了(当然,实际情况是在Windows环境下,_WIN32已经被定义) gcc中的-D选项会默认将宏定义为1,如果要定义为其他的值使用等于号如:-D _WIN32=0
很多的时候,尤其是实际的项目中,我们会使用cmake工具来构建自己的程序。
在cmake中
我们可以在CMakeLists.txt中写入ADD_DEIFNITIONS(-D _WIN32)来添加程序运行时用到的宏。但是这样,一旦我们需要修改使用的宏,就要修改CMakeLists.txt文件,会很麻烦。
这时我们可以这样做:
在CMakeLists.txt中写入
IF(ENVIRO)
ADD_DEFINITIONS(-D _WIN32)
ENDIF(ENVIRO)
这样,我们可以在使用cmake命令的时候加入-D选项,定义ENVIRO 命令如下
cmake -D ENVIRO=1,或者 cmake -D ENVIRO=ON
如果要取消这个定义可以使用: cmake -D ENVIRO=OFF 或 cmake -D ENVIRO=0 或者cmake -U ENVIRO
就写到这里了,希望对你有帮助。。水平有限,有错误的地方还请谅解,并诚邀指正。。
C语言中的条件编译的更多相关文章
- golang项目中使用条件编译
golang项目中使用条件编译 C语言中的条件编译 golang中没有类似C语言中条件编译的写法,比如在C代码中可以使用如下语法做一些条件编译,结合宏定义来使用可以实现诸如按需编译release和de ...
- C语言学习笔记--条件编译
C语言中的条件编译的行为类似于 C 语言中的 if…else…,是预编译指示命令,用于控制是否编译某段代码 . 1.条件编译的本质 (1)预编译器根据条件编译指令有选择的删除代码 (2)编译器不知道代 ...
- c语言中条件编译相关的预编译指令
一. 内容概述 本文主要介绍c语言中条件编译相关的预编译指令,包括#define.#undef.#ifdef.#ifndef.#if.#elif.#else.#endif.defined. 二.条件编 ...
- C语言中的宏定义
目录(?)[-] 简单宏定义 带参数的宏 运算符 运算符 宏的通用属性 宏定义中圆括号 创建较长的宏 较长的宏中的逗号运算符 宏定义中的do-while循环do 空操作的定义 预定义宏 C语言中常用的 ...
- C语言中的调试小技巧
C语言中的调试小技巧 经常看到有人介绍一些IDE或者像gdb这样的调试器的很高级的调试功能,也听人说过有些牛人做工程的时候就用printf来调试,不用特殊的调试器.特别是在代码经过编译器一些比较复杂的 ...
- C语言中头文件怎么写?(本文来源网络,由黑乌鸦进一步完善)
c语言头文件怎么写?我一直有这样的疑问,但是也一直没去问问到底咋回事:所以今天一定要把它弄明白! 其实学会写头文件之后可以为我们省去不少事情,可以避免书写大量的重复代码.有利于整理思路.使代码脉络 ...
- C 语言中的预处理
C 语言中以 # 开头的就是预处理指令,例如 #include . 预处理指令的用途 所有的预处理指令都会在 GCC 编译过程的预处理步骤解析执行,替换为对应的内容.在下一步编译过程中,看不到任何预处 ...
- JAVA语言中的修饰符
JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...
- Java语言中的面向对象特性总结
Java语言中的面向对象特性 (总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知 ...
随机推荐
- hdu 4888 最大流慢板
http://acm.hdu.edu.cn/showproblem.php?pid=4888 添加一个源点与汇点,建图如下: 1. 源点 -> 每一行对应的点,流量限制为该行的和 2. 每一行对 ...
- nodejs 获取文件的编码方式
使用nodejs获取文件夹内文件的编码方式:使用jschardet模块. 下面的代码还有问题,没有添加结束的语句,没有判断应该在哪执行res.send(). res.send()不能放在forEach ...
- Accepted Technical Research Papers and Journal First Papers 【ICSE2016】
ICSE2016 Accepted Paper Accepted Technical Research Papers and Journal First Papers Co-chairs: Wille ...
- 自适应XAML布局经验总结 (四)区域布局设计模式
本系列对实际项目中的XAML布局场景进行总结,给出了较优化的自适应布局解决方案,希望对大家有所帮助. 下面介绍区域布局设计模式. 7. 头尾模式 页面有时分为顶部栏,中间内容和底部栏三部分.这时可以使 ...
- <mvc:annotation-driven />到底帮我们做了啥
一句 <mvc:annotation-driven />实际做了以下工作:(不包括添加自己定义的拦截器) 我们了解这些之后,对Spring3 MVC的控制力就更强大了,想改哪就改哪里. s ...
- Redirect与Transfer 的区别
共同点: 都是重定向: 不同点: redirect: 1发生在客户端: 2.发送两次请求,第一次请求原始页面,当调用此方法时,创建一个应答头,返回状态码302,第二次请求重定向的页面: 3.得不到任何 ...
- Pacemaker 介绍
1. 简介 Pacemaker是一个集群资源管理者.他用资源级别的监测和恢复来保证集群服务(aka.资源)的最大可用性.它可以用你所擅长的基础组件(Corosync或者是Heartbeat)来实现通信 ...
- NRF52840相对于之前的NRF52系列、NRF51系列增加了什么功能
现在广大客户的蓝牙采用NORDIC越来越多了,NORDIC一直在不断进行技术改进更好的满足市场需求 推出了新款NRF52840.NRF52840更为先进些,支持的功能也多点,比如IEEE802.15. ...
- 关于popup
p1.html:点击添加按钮,开启窗口,打开p2.html,填写数据后返回p3.html,p3.html将数据回传到p1.html,且关闭自己 p1.html: <!DOCTYPE html ...
- mybatis源码追踪2——将结果集映射为map
org.apache.ibatis.binding.MapperMethod中execute方法 ...} else if (method.returnsMap()) { result = execu ...