C语言基础

    返回首页    发表留言
本文作者:李德强
          第三节 条件编译
 
 

        接下来我们来一起学习C语言中另一种非常高效的编译机制——条件编译

        在本章第一节中我们已经学习了编译器的编译过程,所有include的头文件和define的宏都会在预编译时被替换成实际代码,也就是宏展开的过程。在今天我们再来学习另外一种预处理机制,也就是上面我们所说的条件编译选项:

    #if
    #ifdef
    #ifndef
    #else
    #elsif
    #end

        这些以#号开头的定义称作条件编译表达式,满足其条件的内容会被编译到预处理的源代码文件中,而不满足条件的内容不会被编译到预处理的源代码中。例如:

 

#define TEST 1
#if TEST == 1
	int a = 1;
#else
	int a = 2;
#endif

 

        可以看到,程序中定义了两个相同的变量,int a =1;和int a = 2;为什么在程序定义两个同名的变量,编译器会顺利编译通过呢?答案就在条件编译选项中:首先我们定义了一宏#if TEST == 1之后又通过#if来判断这个宏的值是否为1,如果为1则只对int a = 1做编译,否则#else只对int b = 2;做编译。所以,在这段代码中只能有一个条件分支的内容被编译器编译。

        由于条件编译只会对满足条件的代码内容做编译,所以我们可以根据需要按条件编译自己的源代码,这样,就会只生成有效的程序代码,这要比只使用条件表达式有效的多。因为在使用条件表达式时计算机会执行条件表达式的判断,从而增加程序的复杂度和执行时间。而使用条件编译,只会在预处理时对其做判断,而生成的程序代码只有满足条件的功能,所以执行效率也会高很多。

        下面我们再来看看另一种条件编译选项#ifndef的用法:我们假设有3个头文件a.h、b.h、c.h和一个源文件hello.c其中a.h中声明了一个函数func()而在b.h和c.h中都包含了a.h。而hello.c又同时包含了b.h和c.h如下:
   

//a.h
void func();
void func()
{
}

//b.h
#include "a.h"

//c.h
#include "a.h"

//hello.c
#include "a.h"
#include "b.h"
#include "c.h"

int main(int argc, char *argv[])
{
	func();
	return 0;
}

 

        于是,问题来了,编译器在编译这段代码时会出现错误,认为函数func()被重复声明了,原因是,在预编译时,a.h中的内容会被替换到b.h和c.h中,而这从个头文件的内容也会被替换到hello.c中,所以func()这个函数的声明就出现了2次。为了解决头文件被重复包含和嵌套的问题,我们可以使用#ifdef和#ifndef来处理,这它们分别表示判断一个宏被定义过,或是未被定义过,再配合#define即可达到头文件不被重复包含的目的,我们来看看对上面例子的修改内容:

//a.h
#ifndef _A_H_
#define _A_H_
void func();

void func()
{
}
#endif

//b.h
#ifndef _B_H_
#define _B_H_
#include "a.h"
#endif

//c.h
#ifndef _C_H_
#define _C_H_
#include "a.h"
#endif

//hello.c
#include "a.h"
#include "b.h"
#include "c.h"

int main(int argc, char *argv[])
{
	func();
	return 0;
}

 

        当预处理开始将a.h替换到b.h中时,编译器会根据#ifndef判断_A_H是否未定义,由于代码中尚未定义这个_A_H宏,所以编译器将#define _A_H编译到源代码中并替换到b.h里,而后将a.h替换到c.h中时,由于_A_H这个宏已经被定义了,所以#ifndef _A_H则为假,不再对其内容进行条件编译,所以整个源文件hello.c虽然包含了这些头文件,但编译器可以根据条件编译选项做处理,从而避免了重复包含头文件。

        另外还有一些其它的条件编译选项例如:#program也可以达到条件编译的目的,但从可读性上讲并没有#ifndef好理解。有兴趣的读者可以自行查阅相关资料学习。我们不再赘述。

    返回首页    返回顶部
  看不清?点击刷新

 

  Copyright © 2015-2018 问渠网 辽ICP备15013245号