天天看点

iOS开发系列--C语言之预处理概述宏定义条件编译文件包含

大家都知道一个c程序的运行包括编译和链接两个阶段,其实在编译之前预处理器首先要进行预处理操作,将处理完产生的一个新的源文件进行编译。由于预处理指令是在编译之前就进行了,因此很多时候它要比在程序运行时进行操作效率高。在c语言中包括三类预处理指令,今天将一一介绍:

<a href="http://www.cnblogs.com/kenshincui/p/3854242.html#macro">宏定义</a>

<a href="http://www.cnblogs.com/kenshincui/p/3854242.html#conditional">条件编译</a>

<a href="http://www.cnblogs.com/kenshincui/p/3854242.html#include">文件包含</a>

对于程序中经常用到的一些常量或者简短的函数我们通常使用宏定义来处理,这样做的好处是对于程序中所有的配置我们可以统一在宏定义中进行管理,而且由于宏定义是在程序编译之前进行替换相比定义成全局变量或函数效率更高。

宏定义实际的操作就是在预处理时进行对应替换,这个阶段不管语法是否正确,而且对于字符串中出现的宏名不会进行替换。宏定义的功能事实上是非常强大的,除了简单的常量替换还可以传入参数:

上面我们可以看出带参数的宏功能很强大,有点类似于函数,同函数不同的是它只是简单的替换,不涉及存储空间分配,参数、返回值等问题,但是由于它在预处理阶段展开,所以一般效率较高。使用带参数的宏需要注意的就是结果最好用括号括起来否则很容易出现问题(在上面的sum例子中我们应该已经看到了);还有一点就是带参数的宏定义时名称和参数之间不要有空格。

条件编译其实就是在编译之前预处理器根据预处理指令判断对应的条件,如果条件满足就将对应的代码编译进去,否则代码就根本不进入编译环节(相当于根本就没有这段代码)。

文件包含指令#include在前面也多次使用过,这里再次强调一下。首先使用#include“xxx”包含和使用#include &lt;xxx&gt;包含的不同之处就是使用&lt;&gt;包含时,预处理器会搜索c函数库头文件路径下的文件,而使用“”包含时首先搜索程序所在目录,其次搜索系统path定义目录,如果还是找不到才会搜索c函数库头文件所在目录。

另外在使用#include的时候我们需要注意包含文件的时候是不能递归包含的,例如a.h文件包含b.h,而b.h就不能再包含a.h了;还有就是重复包含虽然是允许的(这里指的是重复包含头文件)但是这会降低编译性能,不妨看一下下面的例子:

iOS开发系列--C语言之预处理概述宏定义条件编译文件包含

上面有三段代码,在main.c和person.h中都包含了message.h而main.c自身又包含了person.h,这样程序在预处理阶段会对包含内容进行替换,替换后mian.c中包含了两个#include “message.h”虽然没有报错,但这会影响编译的性能,正确的做法应该是这样的:

iOS开发系列--C语言之预处理概述宏定义条件编译文件包含

其实就是用宏定义判断一个宏是否定义了,如果没有定义则会定义这个宏,这样以来如果已经包含过则这个宏定义肯定已经定义过了,即使再包含也不会重新定义了,下面的代码也就不会包含进去。

继续阅读