项目十一 预处理指令
项目概述:
在C语言中,除了前面我学到的语句之外,还有一种特殊的语句叫预处理语句,本项目就是对预处理语句进行学习,这里语句不是实现程序的功能,而是给C程序编译提供很重要的信息,通知C程序进行编译之前做哪些预处理。在这项目我中将会学到预处理的指令学到宏定义以及文件包含,学完此项目对大家编写程序的能力大大的提高。
项目目标
掌握预处理指令概念
掌握文件包含
掌握宏定义的概念
掌握无参数的宏的使用
掌握带参数的宏的使用
掌握条件编译的使用
任务一 预处理指令
任务描述
在从我们接触的第一个C程序的时候,是否还记得第一行代码#include <stdio.h>, 在学常量的时候我们定义了常量用#define,但是我们没有说为什么可以这样定义,本任务通过就来给大家来解决这些我们还没有说的问题,通过对c语言预处理的学习,这些问题将一一打开,并且将对C语言编译系统有全新的认识。
学习目标
掌握文件包含的用法。
掌握宏定义的用法。
掌握条件编译的使用。
相关知识
11-1-1 预处理的概念
预处理是指程序在编译之前对源文件进行简单加工的过程。 C语言提供了多种预处理功能,如宏定义、文件包含、条件编译等,合理地使用它们会使编写的程序便于阅读、修改、移植和调试,也有利于程序的模块化设计。
使用库函数之前,应该用#include引入对应的头文件。这种以#号开头的命令称 为预处理命令。常见预处理命令如表11-1所示。
表 11-1常见的预处理命令
指令 |
说明 |
# |
空指令,无任何效果 |
#include |
包含一个源代码文件 |
#define |
定义宏 |
#undef |
取消已定义的宏 |
#if |
如果给定条件为真,则编译下面代码 |
#ifdef |
如果宏已经定义,则编译下面代码 |
#ifndef |
如果宏没有定义,则编译下面代码 |
11-1-2 文件包含
#include"文件名"在前面已多次用此命令包含过库函数的头文件。例如:#include"stdio.h",我们管这种预处理称为文件包含。
它的语法格式有两种,具体如下:
格式一:
#include <文件名>
格式二:
#include "文件名"
文件包含命令的功能是把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件,比如我们想要使用printf()函数之前就要先引入#include <stdio.h>。
11-1-3 宏定义
在学常量的时候,我们将PI定义成#define 3.14这种形式,这种形式就叫做宏定义,宏定义分为带参数的宏定义和不带参数的宏定义。
1.不带参数的宏定义
为了避免程序书写错误,可以使用不带参数的宏定义来表示这些常量,其语法格式如下所示:
#define 宏名 字符串
说明
(1)宏名,是标识符的 一种,命名规则和变量相同,要遵守标识符的命名规则。
(2)字符串可以是数字、表达式、if 语句、函数等。
这里所说的字符串是一般意义上的字符序列,不要和C语言中的字符串等同, 它不需要双引号 “字符串”可以是常数、表达式、格式串等。
(3)宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。
(4)如要终止其 作用域可使用#undef命令
为了帮助大家更好地掌握宏定义的使用,接下来通过一个案例演示。
实例11- 1 不带参数的宏定义的使用。
#define PI 3.14159
#include<stdio.h>
#define Pi 3.1415926
int main()
{
double r,s;
printf("请输入圆的半径\n");
scanf("%lf",&r);
s=Pi*r*r;
printf("圆的面积为: %lf",r);
return 0;
}
#undef PI //取消宏定义
void func(){
printf("PI=%f", PI);
}//错误,这里不能使用到PI了
带参数的宏定义不是仅仅进行简单的字符串替换,还要进行参数替换。其语法格式如下所示:
#define 标识符(宏名)(参数表) 字符串
字符串中包含在括号中所指定的参数。
例如:#define S(a,b) a*b;
int area=S(3,4);
程序中使用了宏定义替代了原来的S=a*b,就像定义了一个公式一样,很方便。接下来我们使用带参数的宏定义一个计算圆面积的程序。
实例11- 2 带参数的宏定义的使用。
#include<stdio.h>
#define Pi 3.1419526
#define S(r) Pi*r*r
int main()
{
double r,s;
printf("请输入圆的半径\n");
scanf("%lf",&r);
s=S(r);
printf("圆的面积为: %lf",s);
return 0;
}
运行结果如图所示 11-1所示。
图11- 1实例11-2运行结果
上述案例就是带参数的宏定义,很显然带参数的宏定义在计算的时候,不必做更多的计算声明,就可以直接的套用,它更加适合于那些需要大量使用该公式的程序中,相反如果程序中仅仅使用一次,使用该公式的话,不带参数的宏定义更加高效。
11-1-4 条件编译
C语言预处理程序提供了条件编译的功能,可以按不同的条件去编译不同的程序部分,以产生不同的目标代码文件。这对于程序的移植和调试是很有用处的。
一般情况下,最常见的条件编译指令是#if/#else/#endif指令,看名字就知道,跟我们平时用的if、elseif、else是 一样的,不同的是这里一定要记得 #endif,一般情况下这三种指令是结合在一起使用的其语法格式如下:
#if 常数表达式
程序段 1
#else
程序段 2
#endif
说明:在上述的语法中,当表达式值为非0时,编译“程序段1”,不编译“程序段2”;否则,只编译“程序段2”。如果只有一种情况下,#else语句可以省略。
接下来我们一起来看一个案例
实例11- 3 条件编译的使用。
#include<stdio.h>
#define DEBUG 1
int main(){
printf("常量值是%d对应的输出的英文\n",DEBUG);
#if DEBUG
printf("one");
#else
printf("two");
#endif
getchar();
return 0;
}
运行的结果 如图11-2所示。
图11- 2 实例 11-3运行结果
上述的案例中,因为定义的常量是1,直接走成立的程序段。