第7章预处理程序 ·59* 第7章预敵处理程序 7.1什么是预处理程序 预处理程序是一些行首以#开始的特殊语句,例如:#include,#define等就是预处 理语句。在编译程序的编译过程中,进行其它编译处理(词法分析、语法分析、代码生成、优 化和连接等)之前,先讲行这些语句的分析处理。 预处理语句使用的目的在于帮助程序员编写出易读、易改、易移植并便于调试的程序 预处理语句主要有四种: 宏定义和宏替换、文件包含、条件编译和行控制。 预处理语句的作用范围是从被定义语句开始直至被解除定义或是到包含它的文件结术为 止均有效。 7.2宏定义和宏替换 “宏”是借用汇编语言中的概念。为的是在C语言程序中方便的作一些定义和扩展。这些 语句以#define开头,分为两种:符号常量的宏定义和带参数的宏定义。 1符号常量的宏定义和宏替换 符号常量的宏定义语句是一般格式: #define标识符字符串 其中标识符就叫作宏名称。 注意:标识符与字符串之间不要用‘=’,结尾不要加‘:'。 2.带有参数的宏定义及其替换 复杂的宏定义带有参数列表,参数列表中可有不止一个参数,其一般格式: 标识符(参数列表)字符 对带有参数的宏定义进行宏替换时,不仅对宏标识符作字符串替换,还必须作参数的替 。 例如: #define So(x)((x)(x)) 那么SQ(ab)将被宏替换成(a+b)*(ab)。 宏定义也可嵌套使用,即一个宏定义可用另一个宏定义来定义。例如: #define SQ(x)((x)*(x)) #define CUBE(x)(SQ(x)*(x)) 3.宏定义类函数 宏定义常用于把直接插入的代码来代替函数,以提高执行效率。这一类的宏,就称做宏 定义类函数,例如: define MIN(x,y)(((x)<(y))?(x)(y)) 有了这样的宏之后,就可以直接引用,例如: m=MIN(a,b):
第 7 章 预处理程序 ·59· 第 7 章 预处理程序 7.1 什么是预处理程序 预处理程序是一些行首以#开始的特殊语句,例如:#include,#define 等就是预处 理语句。在编译程序的编译过程中,进行其它编译处理(词法分析、语法分析、代码生成、优 化和连接等)之前,先进行这些语句的分析处理。 预处理语句使用的目的在于帮助程序员编写出易读、易改、易移植并便于调试的程序。 预处理语句主要有四种: 宏定义和宏替换、文件包含、条件编译和行控制。 预处理语句的作用范围是从被定义语句开始直至被解除定义或是到包含它的文件结术为 止均有效。 7.2 宏定义和宏替换 “宏”是借用汇编语言中的概念。为的是在 C 语言程序中方便的作一些定义和扩展。这些 语句以#define 开头,分为两种:符号常量的宏定义和带参数的宏定义。 1.符号常量的宏定义和宏替换 符号常量的宏定义语句是一般格式: #define 标识符 字符串 其中标识符就叫作宏名称。 注意:标识符与字符串之间不要用‘=’,结尾不要加‘;’。 2.带有参数的宏定义及其替换 复杂的宏定义带有参数列表,参数列表中可有不止一个参数,其一般格式: #define 标识符(参数列表) 字符串 对带有参数的宏定义进行宏替换时,不仅对宏标识符作字符串替换,还必须作参数的替 换。 例如: #define SQ(x) ((x)*(x)) 那么 SQ(a+b)将被宏替换成(a+b)*(a+b)。 宏定义也可嵌套使用,即一个宏定义可用另一个宏定义来定义。例如: #define SQ(x) ((x)*(x)) #define CUBE(x) (SQ(x)*(x)) 3.宏定义类函数 宏定义常用于把直接插入的代码来代替函数,以提高执行效率。这一类的宏,就称做宏 定义类函数,例如: #define MIN(x,y) (((x)<(y))?(x):(y)) 有了这样的宏之后,就可以直接引用,例如: m=MIN(a,b);
·60. C程序设计要点分析与题解 这语句将被预处理成: =(a)<(b)?(a):) 7.3文件包含 文件包含是指一个程序文件将另一个指定义文件的内容包含进来,用#include语句来 说明 般有两种格式: #include<文件名> (2)#include ”文件名” 第一种,用尖括号表示在标准库目录下找该文件:第二种,用双引号表示先在当前目录 (源文件所在目录)中找包含文件,若找不到,再到标准库目录中找。系统的标准库文件都是,h 文件。例如 #include <stdio.h> /标准输入输出的基本常量和宏或函数文件* #include<string.h>/体串函数文件*材 #include<malloc.h>/*内存分配函数文件*/ #include <ctype.h> /*字符函数文件*/ #include <math.h> /数学雨库文件案/ 用文件包含, 可以减 少重复工作,提高程序正确性 还便于维护修改。程序员可以把自 己常用的一些符号常量、类型定义和带参数的宏定义,以及一些常用自编函数都放在.文件 中,通过#include语句包含引用之。 7.4条件编译 提供条件编译措施使同一源程序可以根据不同编译条件(参数)产生不同的目录代码,其 作用在于便于调试和移植。 条件编译控制语句有不同形式,下面分别讨论。 1.#ifdef语句及其使用 一般格式: #ifdef标识符 语句块1 #else 语句块2 #endif 7.4格式化输入/输出 格式化的控制台1/0函数有两种,它们都与标准10库有关。源程序开头应包含标准输 入输出头文件:
·60· C 程序设计要点分析与题解 这语句将被预处理成: m=(((a)<(b))?(a):(b)); 7.3 文件包含 文件包含是指一个程序文件将另一个指定义文件的内容包含进来,用#include 语句来 说明。 一般有两种格式: (1) #include <文件名> (2) #include ″文件名″ 第一种,用尖括号表示在标准库目录下找该文件;第二种,用双引号表示先在当前目录 (源文件所在目录)中找包含文件,若找不到,再到标准库目录中找。系统的标准库文件都是.h 文件。例如: #include <stdio.h> /* 标准输入输出的基本常量和宏或函数文件 */ #include <string.h> /* 串函数文件 */ #include <malloc.h> /* 内存分配函数文件 */ #include <ctype.h> /* 字符函数文件 */ #include <math.h> /* 数学函数库文件 */ 用文件包含,可以减少重复工作,提高程序正确性,还便于维护修改。程序员可以把自 己常用的一些符号常量、类型定义和带参数的宏定义,以及一些常用自编函数都放在.h 文件 中,通过#include 语句包含引用之。 7.4 条件编译 提供条件编译措施使同一源程序可以根据不同编译条件(参数)产生不同的目录代码,其 作用在于便于调试和移植。 条件编译控制语句有不同形式,下面分别讨论。 1.#ifdef 语句及其使用 一般格式: #ifdef 标识符 语句块 1 #else 语句块 2 #endif 7.4 格式化输入/输出 格式化的控制台 I/O 函数有两种,它们都与标准 I/O 库有关。源程序开头应包含标准输 入输出头文件:
第7章预处理程序 ·61· #include <stdio.h> 1.printf() printf(O函数功能为按指定格式输出显示各种基本类型数据,其一般格式: printf(“控制串”,参数列表) 控制串分两部分,即:要显示的字符和格式串。格式串以“%”开头,后跟格式码。格式 串与参数一一对应。 2.scanf() scanf0的功能是读入各种类型数据,并自动将其转换为恰当的格式,其一般格式为: scanf(“控制串”,参数列表) 控制串与前述printf()中的控制串类似,也包含有以“%”开头加格式码组成的格式串。 参数列表所列出的应当是变量的地址,而不是变量名
第 7 章 预处理程序 ·61· #include <stdio.h> 1.printf() printf()函数功能为按指定格式输出显示各种基本类型数据,其一般格式: printf(“控制串”,参数列表) 控制串分两部分,即:要显示的字符和格式串。格式串以“%”开头,后跟格式码。格式 串与参数一一对应。 2.scanf() scanf()的功能是读入各种类型数据,并自动将其转换为恰当的格式,其一般格式为: scanf(“控制串”,参数列表) 控制串与前述 printf()中的控制串类似,也包含有以“%”开头加格式码组成的格式串。 参数列表所列出的应当是变量的地址,而不是变量名