您的位置:首页 > 其它

预处理指令—宏定义,条件编译,文件包含

2015-04-19 15:21 453 查看
一.预处理指令

1.C语言在对源程序进行编译之前,会先对一些特殊的预处理指令作解释(比如之前使用的#include文件包含指令),产生一个新的源程序(这个过程称为编译预

处理),之后再进行通常的编译(预处理指令在代码翻译成0和1之前执行)

2.为了区分预处理指令和一般的C语句,所有预处理指令都以符号"#"开头,并且结尾不用分号

3.预处理指令可以出现在程序的任何位置,它的作用范围是从它出现的位置到文件尾。习惯上我们尽可能将预处理指令写在源程序开头,这种情况下,它的作

用范围就是整个源程序文件

4.C语言提供的预处理指令主要有:宏定义、文件包含、条件编译

二.宏定义

1.不带参数的宏定义

(1)一般形式: #define 宏名 字符串(比如:#define ABC 10),右边的字符串也可以省略,比如:#define ABC

(2)作用:它的作用是在编译预处理时,将源程序中所有“宏名”替换成右边的“字符串”,常用来定义常量。

(3)使用习惯与注意:

<1>宏名用大写字母

<2>对程序中用双引号括起来的字符内的字符,是不进行宏的替换操作。

<3>在编译预处理用字符串替换宏名时,不作语法检查,只是简单的字符串替换。只有在编译的时候,才对已经替换宏名的源程序进行语法检查。

<4>宏名的有效范围是从定义位置到文件结束,如果需要终止宏定义的作用域,可以用#undef命令(作用域截止)。

<5>定义一个宏时可以引用已经定义的宏名

2.带参数的宏定义

(1)一般形式:#define 宏名(形参数列表) 字符串

(2)作用:在编译预处理时,将源程序中所有宏名宏名(实参数列表)成字符串,并且将字符串中的形参数用宏名右边实参数列表中的参数替换。

#include <stdio.h>

#define average(a, b) ((a)+(b)/2)

int main ()
{
int a = average(10, 4);  // 会被替换成:int a = (10+4)/2

printf("平均值:%d", a);
return 0;
}

(3)使用注意:

<1>宏名和参数列表之间不能有空格,否则空格后面的所有的所有字符串都作为替换的字符串。

<2>带参数的宏在展开时,只作简单的字符和参数的替换,不进行任何计算操作。所以在定义宏时,用一个小括号括住字符串的参数,并且计算结果也用括号括起来:a+b要写成((a)+(b))

(4)与函数的区别
从整个使用过程可以发现,带参数的宏定义,在源程序中出现的形式与函数很像。但是两者是有本质区别的:

<1> 宏定义不涉及存储空间的分配、参数类型匹配、参数传递、返回值问题

<2> 函数调用在程序运行时执行,而宏替换只在编译预处理阶段进行。所以带参数的宏比函数具有更高的执行效率

二.条件编译

在很多情况下,我们希望程序的其中一部分代码只有在满足一定条件时才进行编译,否则不参与编译(只有参与编译的代码最终才能被执行),这就是条件编译。

1.基本用法

#if 条件1
代码1
#elif 条件2
代码2
#else
代码3
#endif

(1)如果条件1成立,那么编译器就会把#if 与 #elif之间的代码1代码编译进去(注意:是编译进去,不是执行,和平时用的if-else是不一样的)

(2)如果条件1不成立、条件2成立,那么编译器就会把#elif 与 #else之间的代码2代码编译进去。

(3)如果条件1、2都不成立,那么编译器就会把#else 与 #endif之间的代码3编译进去。

(4)注意,条件编译结束后,一定要在最后面加一个#endif,不然后果很严重(endif是不参加编译的结束标准,不写的话,后面全部都会消失,不会参加编译)。

(5)#if 和 #elif后面的条件一般是判断宏定义而不是判断变量,因为条件编译是在编译之前做的判断,宏定义也是编译之前定义的,而变量是在运行时才产生的、才有使用的意义。

(6)例子:

#define MAX 25

int main()
{
#if MAX == 0
printf("MAX是0");
#elif MAX > 0
printf("MAX大于0");
#else
printf("MAX大于0");
#endif
return 0;
}


2.其它用法

(1)#if define() 和if !defined()的用法
<1>#if和#elif后面的条件不仅仅可以用来判断宏的值,还可以判断是否定义过某个宏

#if defined(宏) // 判断这个宏定义过没有,定义过则执行代码
代码
#endif

<2>if !defined(宏)是判断这个宏如果没有定义,则执行代码。

(2)#ifdef和ifndef的使用

<1>#ifdef的使用和if defined()的用法一致,只是一个不写括号,一个要写括号
<2>#ifndef的使用和if !defined()的用法一致,只是一个不写括号,一个要写括号

三.文件包含

1.其实我们早就有接触文件包含这个指令了, 就是#include,它可以将一个文件的全部内容拷贝另一个文件中。

2.一般形式:
<1>第一种形式:#include <文件名> (直接到C语言库函数头文件所在的目录中查找文件)
<2>第二种:#include "文件名"(系统会先在源程序当前目录下寻找,若找不到,再到操作系统的path路径中查找,最后才到C语言库函数头文件所在目录中查找)

3.使用注意
(1)#include指令允许嵌套包含,比如a.h包含b.h,b.h包含c.h,但是不允许递归包含,比如 a.h 包含 b.h,b.h 包含 a.h。

(2)使用#include指令可能导致多次包含同一个头文件,降低编译效率。解决办法:
把函数声明写在这段代码中间:
#ifndef _文件名_H_
#define _文件名_H_
函数声明代码
#endif
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编译器 C
相关文章推荐