由于C++兼容C语法,所以我们这里介绍的虽然是C的条件编译,但是在C++中也是这样的。

一、条件编译的作用

其实是从“条件编译”这个名字上就能看出,所谓“条件编译”其实就是“按照条件去编译”

也就是“预编译”时,预编译器处理“条件编译”时,可以通过“条件编译”帮你保留某些代码、
以及帮你去掉某些代码,第二阶段编译时就只编译保留的代码

一般情况下,C源程序中的每一行代码都要参加编译的,但有时候出于对程序代码优化的考虑、
或者其它方面的考虑,我们只希望对其中一部分内容进行编译,此时就需要在程序中加上条件(条件编译),
让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃

文件:a.c

#include <stdio.h>

#define NUM1

int main(void)
{
    int a = 0;

    #ifdef NUM1
    a += 10;
    #endif

    #ifdef NUM2
    a += 1000;
    #endif
}

比如以上这个a.c,预编译器在对a.c进行预编译时,由于只定义了NUM1宏,没有定义NUM2宏,
所以预编译后,main函数中只留下了int a += 10;

预编译后,main函数最后就变为了如下样子:

int main(void)
{
    int a = 0;
    int a += 10;
}

二、C 初学者对条件编译的误解

对于很多C的初学同学来说,往往误认为条件编译可有可无,它是一个不重要的东西

误解的原因

  1. 初学C语言时,写的练习程序都太简单了,几乎用不到
  2. 初学时很少阅读复杂C源码,很难接触别人写的包含大量条件编译的代码,很少阅读的原因,
    一个是因为没有工作环境的支持,你阅读不到,第二个就算接触到了,你也根本看不懂

除了复杂宏定义外,其实条件编译也是阻碍我们阅读复杂C源码的难关之一

在复杂的C代码中,往往到处都充满了条件编译这个东西,如果你搞不定条件编译,
你很难读懂复杂的C代码,但是在实际与C相关的开发中,
阅读复杂的OS、库、驱动、框架代码确又是家常便饭的事情


三、为什么条件编译在实际开发中这么重要

因为实际开发的C程序,往往因为各种原因,需要在同一个程序中编写出针对不同情况(比如不同OS、硬件环境)的代码,
编译程序时为了编译得到针对不同情况的可执行程序,我们需要使用条件编译来做选择

疑问:为什么不直接全部编译呢?

这样子会导致我们的可执行程序非常大,因为里面不仅包含了我们需要的代码,还包含了很多用不到的代码,
但是使用条件编译将不需要的代码去掉后,就不存在这样的情况了

程序变小之后,程序不管是静态存储在硬盘上,还是运行在内存中时,将会非常节省计算机的硬盘空间和内存空间


四、什么情况下需要使用条件编译

  1. 文件内容被重复include时,去掉重包含的内容
  2. 实现程序的跨平台
  3. 辅助调试程序

有关这三种情况,我们后面再详细说


五、常见的条件编译有哪些,基本用法是怎样的

1. 条件编译种类概述

对于条件编译,关键是理解而不是死记硬背只要你理解了,就算忘了怎么写了,上网上一查便知

条件编译主要有两种:

第一种:#ifdef#ifndef

  • (a)ifdefif defined的缩写
  • (b)ifndefif ndefined的缩写
    由于#ifndef的功能与#ifdef刚好相反,所以只要理解了#ifdef,就一定能理解#ifndef

为了面对更复杂的情况,#ifdef#ifndef往往还会和#else的搭配

第二种:#if
为了得到更复杂的用途,#if往往会和defined#elif#else的搭配

不管那种情况,结尾时都是必须使用#endif结尾,这是固定格式

2. 条件编译所包含的可以是任何内容

你需要对什么进行条件编译,条件编译就可以包含什么内容,这个是根据你自己需求来定的

(a)可以是#include <***>

#ifdef ***

#include <****.h>
#include <****.h>
...

#endif

(b)整个函数

#ifndef ***
int fun(int a, int b)
{
...
}

#endif

(c)函数内部的部分代码

int fun(int a)
{
    #if ***
    int b = 100;
    ...

    #else
    ...

    #endif
    ...
    ...
    ...
}

(d)类型定义,变量定义

#if ***
struct student
{
    #ifdef ***
    int num;
    ...
    #endif
    ...
};

struct student stu;
int gbl_va = 100;

#endif

(e)整个文件的内容stdio.h

#ifndef _STDIO_H_
...
...
//整个头文件的内容


#endif

为了简单,我们再给大家演示条件编译如何使用时,我们只在.c文件中演示,
但是实际上在.h文件中,条件编译的使用是一样的,因为.h中的内容被包含到.c中后,
其实还是变成了.c的一部分