通常情况,我们想让程序选择性地执行,多会使用分支语句,比如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语言中的条件编译的更多相关文章

  1. golang项目中使用条件编译

    golang项目中使用条件编译 C语言中的条件编译 golang中没有类似C语言中条件编译的写法,比如在C代码中可以使用如下语法做一些条件编译,结合宏定义来使用可以实现诸如按需编译release和de ...

  2. C语言学习笔记--条件编译

    C语言中的条件编译的行为类似于 C 语言中的 if…else…,是预编译指示命令,用于控制是否编译某段代码 . 1.条件编译的本质 (1)预编译器根据条件编译指令有选择的删除代码 (2)编译器不知道代 ...

  3. c语言中条件编译相关的预编译指令

    一. 内容概述 本文主要介绍c语言中条件编译相关的预编译指令,包括#define.#undef.#ifdef.#ifndef.#if.#elif.#else.#endif.defined. 二.条件编 ...

  4. C语言中的宏定义

    目录(?)[-] 简单宏定义 带参数的宏 运算符 运算符 宏的通用属性 宏定义中圆括号 创建较长的宏 较长的宏中的逗号运算符 宏定义中的do-while循环do 空操作的定义 预定义宏 C语言中常用的 ...

  5. C语言中的调试小技巧

    C语言中的调试小技巧 经常看到有人介绍一些IDE或者像gdb这样的调试器的很高级的调试功能,也听人说过有些牛人做工程的时候就用printf来调试,不用特殊的调试器.特别是在代码经过编译器一些比较复杂的 ...

  6. C语言中头文件怎么写?(本文来源网络,由黑乌鸦进一步完善)

      c语言头文件怎么写?我一直有这样的疑问,但是也一直没去问问到底咋回事:所以今天一定要把它弄明白! 其实学会写头文件之后可以为我们省去不少事情,可以避免书写大量的重复代码.有利于整理思路.使代码脉络 ...

  7. C 语言中的预处理

    C 语言中以 # 开头的就是预处理指令,例如 #include . 预处理指令的用途 所有的预处理指令都会在 GCC 编译过程的预处理步骤解析执行,替换为对应的内容.在下一步编译过程中,看不到任何预处 ...

  8. JAVA语言中的修饰符

    JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...

  9. Java语言中的面向对象特性总结

    Java语言中的面向对象特性 (总结得不错) [课前思考]  1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类?  2. 面向对象编程的特性有哪三个?它们各自又有哪些特性?  3. 你知 ...

随机推荐

  1. 修改jenkins启动的默认用户

    # 背景 通过yum命令安装的jenkins,通过service jenkins去启动jenkins的话,默认的用户是jenkins,但jenkins这个用户是无法通过su切换过去的 ,在某些环节可能 ...

  2. NET 下载共享文件

    执行 public static void Run() { "); if (state) { // 共享文件夹的目录 TransportRemoteToLocal(@"\\192. ...

  3. 关于linq的几个小例子

    private void button1_Click(object sender, EventArgs e) { ] { ,,,,,,}; var result0 = from num in numb ...

  4. VisualStudio神级插件Resharper的基本配置和使用技巧大全+Resharper性能优化

    所谓工欲善其事,必先利其器.尽管visual studio本身已经非常强大,但优秀的插件仍然可以帮开发者大大提高效率. ReSharper是一款由jetbrain开发的针对C#,VB.NET,ASP. ...

  5. Spring Batch学习笔记(一)

    Spring Batch简介 Spring Batch提供了可重复使用的功能,用来处理大量数据.包括记录.跟踪,事务管理,作业处理统计,作业重启,跳过和资源管理. 此外还提供了更高级的技术服务和功能, ...

  6. ABP框架踩坑记录

    ABP框架踩坑记录 ASP.NET Boilerplate是一个专用于现代Web应用程序的通用应用程序框架. 它使用了你已经熟悉的工具,并根据它们实现最佳实践. 文章目录 使用MySQL 配置User ...

  7. 用MVC5+EF6+WebApi 做一个考试功能(五) 前端主题

    内容概述 前面絮絮叨叨没正事,到现在为止也没有开始写代码,不过在考虑下貌似这一节还是开始不了. B/S架构开发有一个特点,就是用浏览器打开,不同的用户群体可能有不同的风格,不论是管理平台还是普通的网站 ...

  8. 配置阿里yum源,设置命令

    配置阿里yum源 #linux的软件包管理 安装 软件的方式有三种 .源代码编译安装() .下载python3的源代码 .解压缩源代码 .进入源代码目录,开始编译安装 .配置环境变量 .yum方式安装 ...

  9. python 进程、线程、协程感悟

    进程: 感觉只是使用Process模块加以使用即可: # -*- coding: utf-8 -*- # data:2019-02-23 21:23 # user:DIY # file:thread_ ...

  10. php 删除二维数组中某个key值

    /** * 根据key删除数组中指定元素 * @param array $arr 数组 * @param string/int $key 键(key) * @return array */ priva ...