首页 /  技术专区  /  C 宽屏模式 >

条件编译初认识

1. 条件编译

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


1.1 条件编译的作用

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

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

一般情况下,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;
}

如此就实现了代码的选择。

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

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

(1)误解的原因

        1)初学C语言时,写的练习程序都太简单了,几乎用不到。

        2)初学时很少阅读复杂C源码,很难接触别人写的包含大量条件编译的代码很少阅读的原因,一个是因为没有工作环境的支持,你阅读不到,第二个就算接触到了,你也根本看不懂。

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

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

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

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

当然程序中并不是所有的代码都需要使用条件编译来选择,只有哪些需要被选择的代码,我们才会对其使用条件编译。

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

这样子会导致我们的可执行程序非常大,因为里面不仅包含了我们需要的代码,还包含了很多用不到的代码。

但是使用条件编译将不需要的代码去掉后,就不存在这样的情况了。

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

特别是当你的程序非常庞大时,又或者是当你的计算机资源本来就不是很足时,这一点就显得更重要了。

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

        (1)文件内容被重复include时,去掉重包含的内容

        (2)实现程序的跨平台

        (3)辅助调试程序

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

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

1.5.1 条件编译种类概述

(1)对于条件编译,关键是理解而不是死记硬背

        只要你理解了,就算忘了怎么写了,上网上一查便知。

(2)条件编译种类

        条件编译主要有两种:

        1)第一种:#ifdef、#ifndef

        (a)ifdef:if defined的缩写

        (b)ifndef:if ndefined的缩写

        由于#ifndef的功能与#ifdef刚好相反,所以只要理解了#ifdef,就一定能理解#ifndef。

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

        2)第二种:#if 

        为了得到更复杂的用途,#if往往会和defined、#elif、#else的搭配。

        #elif:else if的缩写,类似c语法中的else if

(3)注意

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

#ifdef ***         
...                
#endif
#if ***
...
#endif

#endif表示结束该条件编译。

#ifdef、#if 好比{

#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

3)#elif、#else、defined等,只能与#if #ifdef搭配使用,不能独立使用

(a)错误的写法

比如:

#elif ***
...
#endif
#else 
...
#endif

(b)正确写法

比如:

#if ***
...
#elif
...
#else
...
#endif
#ifdef ***
...
#else
...
#endif

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


头像
0/200
图片验证码