内容正文:
第9章编译预处理、结构体和共同体
概述
9.1
编译预处理
9.2
结构体
9.3
共同体
9.4
对于一个C程序来讲,不仅要求程序能实现要实现的功能,而且还要力求程序最优化。例如要结构简明,可读性好;少量的改动就能满足不同的要求,适应性强;占用内存空间少,内存开销小等。本章将介绍编译预处理、结构体和共同体等知识,使用这些知识可以进一步优化程序的设计环境,编写出更加清晰、通用、紧凑和高效的程序。
【学习目标】
· 掌握有关编译预处理的知识
· 掌握对简单的结构体的运用
· 了解有关共同体的知识
9.1 概述
编译预处理是指在编译C语言程序之前,预先对以“#”开头的命令行所指定的标识符、常量、表达式或文件等进行处理,目的在于帮助用户设计出易读、易改、易移植的程序。在程序设计中合理地使用预处理,可大大提高程序的执行效率。
结构体和共同体都是C语言中典型的复杂数据类型,与数组一样也包含多个数据“成员”;但是与数组不同的是,结构体和共同体中的数据成员可以分属于不同的数据类型,这样为程序设计提供了更加丰富的手段。
结构体与共同体的区别在于:结构体把几种不同类型的数据组成1个整体,其中每个成员都要分别占用独立的内存空间;而共同体是把几种不同类型的数据存放到同一段内存单元中,每一时刻只有1个数据有效,它比前者节约内存空间,但每一时刻只有1个数据可使用。
9.2 编译预处理
严格地说,预处理命令并不是C语言本身的组成部分,而是为了方便用户,ASCII标准规定可以加入到C源程序中的命令。一般用户编写程序都要经过如下3个步骤才能实现其功能:
· 编译预处理;
· 编译;
· 链接。
编译预处理的作用是将预处理名(宏名)中所包含的内容用文件、字符串等代替。此外,使用条件编译可以对程序中的代码行有选择性地进行编译。
例如,若程序中有代码“#include<stdio.h>”,则它表示使用文件“stdio.h”中的全部内容代替该命令。1个预处理命令可以写在程序中的任何位置,且从书写位置开始到文件结束有效,但通常的做法是写在程序的开头,以保持程序结构的清晰,增强程序的可读性。
只有正确区分编译预处理命令和C语句、正确区分程序的预处理过程和编译过程,才能正确使用编译预处理命令。能否使用编译预处理命令是C语言与其他高级语言的一个重要区别,C语言提供预处理功能主要有以下3种:
· 宏定义;
· 条件包含;
· 条件编译。
1.宏定义
宏定义也称宏替换,是一种以“#define”开头的命令,其基本功能是用1个标识符来代表1个常数或一段程序代码。宏定义有两种形式:带参数的宏和不带参数的宏。
(1)不带参数的宏
基本格式:
#define 宏名 宏体
例如:#define PI 3.1415926
(2)带参数的宏
基本格式:
#define 宏名(参数1,参数2……) 宏体
例如:#define S(r) PI*(r)*(r)
(3)不带参数的宏的执行
程序中以“宏名”形式出现的内容都用“宏体”代替(引号中的内容除外)。
例如,有以下定义:
#define PI 3.1415926
则在程序中所有的符号“PI”都用3.1415926来代替。
(4)带参数的宏的执行
对于带有参数形式的“宏”,其功能得到了增强,其用法与函数相似。在处理带参数的“宏”时,系统分两步执行,即先用宏体替换掉宏名,再用参数的实际值替换掉参数。
2.文件包含
文件包含是指在程序中通过“#include”命令将另一个文件的全部内容嵌入到本程序中来。而使用条件编译可以对程序中的代码行进行选择性编译。
文件包含主要有以下两种格式。
· #include<文件名>:使用这种格式时,系统将到存放C语言库函数头文件所在的目录中查找要包含的文件。
· #include"文件名":使用这种格式时,系统先到用户保存C程序文件的当前目录中寻找要包含的文件,如果找不到,再到存放C语言库函数头文件所在的目录中查找要包含的文件。
$