
C语言程序ch8编译预处理.ppt
21页第八章本章主要内容本章主要内容3.了解条件了解条件编译编译命令命令 C的源程序的源程序 预处理理 编译 目目标程序程序 ((*.C) _______________ (*.OBJ)编译系系统中有中有 : 预处理程序理程序 编译程序程序Ø宏替换 #define N 20 Ø文件包含 #include<>Ø条件编译 if( ... ) • C中的中的预处理命令理命令分分类类宏定宏定义义有两种有两种类类型型:字符串替字符串替换换和和带带参数的宏替参数的宏替换换 1 字符串宏替字符串宏替换换§ 功能:功能:在在预处预处理理时时 ,将程序中宏定将程序中宏定义义之后出之后出现现的的所有的宏名所有的宏名,用宏替用宏替换换体代替宏替宏替换名名宏替宏替换体体§ 格式:格式:#define 标识符 字符串符 字符串 C的的编译程序程序调用用预处理程序理程序检查有否有否宏名宏名,若有,,若有,用用宏替宏替换体体将其替将其替换,完成之后,将替,完成之后,将替换后的源程序后的源程序交交该编译程序8.1 8.1 宏定宏定义义§ 用途用途: 常用的符号常数常用的符号常数 数数组组的的长长度度 #define N 10 /* 编译编译之前用之前用10替替换换所有的所有的N */…….int a[N]§ 说说明明:v 通常放在程序开通常放在程序开头头, ,不加分号不加分号v 是代替是代替, ,不是不是赋值赋值( (不作不作语语法法检查检查) )v 可将多个可将多个语语句或表达式定句或表达式定义为义为一个宏替一个宏替换换v 区区别变别变量和关量和关键键字字, ,习惯习惯用大写用大写#define L 2.0*PI*R#define S PI*R*Rv 双引号中的不替双引号中的不替换换v 有效范有效范围围, ,从定从定义义开始到程序开始到程序结结尾尾main( ) { printf (“PI=%f\n”,PI); }结结果:果:main( ) { printf(“PI=%s\n”,”PI”); }v 可以嵌套可以嵌套, ,后定后定义义的宏可以包含先定的宏可以包含先定义义的宏名的宏名结结果果::PI=PI2 带带参数的宏定参数的宏定义义 带带参数的宏不参数的宏不仅仅能能进进行字符串代替,而且行字符串代替,而且还进还进行参数代行参数代换换。
§ 格式:格式: #define 宏名(参数表)宏名(参数表) 表达式表达式§ 功能功能:: 带参数的宏将一个参数的宏将一个带形参形参的表达式定的表达式定义为一个一个带参数参数的宏名,的宏名,预处理程序理程序对程序中所有程序中所有带实参参表的宏名表的宏名进行行宏宏展开展开替替换,,用表达式代替宏名,用参数表中的用表达式代替宏名,用参数表中的实参代替表参代替表达式中达式中对应的形参的形参例:例:#define S( a, b) a*b程序中程序中 S(3, 2) 3*2§ 用途:用途:用用带参数的宏可以代表一些参数的宏可以代表一些简短的表达式,提高短的表达式,提高程序程序执行的效率行的效率 * 宏定宏定义可以嵌套可以嵌套* * 对对常用的格式常用的格式输输入入输输出函数出函数printfprintf可以可以进进行宏定行宏定义义,使程序,使程序简简化化* *宏名与参数的宏名与参数的圆圆括号之括号之间间不能有空格不能有空格 s (a,b) s (a,b)§ 说明:明:* 宏定宏定义义命令要求在一行内写完,如命令要求在一行内写完,如换换行,用行,用“\”表表示下一行示下一行继续继续。
* 对对于宏定于宏定义义的形参要根据需要加上的形参要根据需要加上圆圆括号,以免括号,以免 发发生运算生运算错误错误[例例1] 使用有参宏替使用有参宏替换换求园的面求园的面积积 #define S(r) PI*r*r main() {float a=3.6,area; area=S(a); printf(“r=%f\narea=%f\n”,a,area); }[例例2] 求下列求下列语语句的循句的循环环次数 #include “stdio.h” #define N 2 #define M N+1 #define NUM (M+1)*M/2 main() { int i,n=0; for(i=1;i<=NUM;i++) {n++; printf(“%d”,n); } }8函数要求形参,函数要求形参,实实参有参有类类型(相同)型(相同) 宏的形参,宏的形参,实实参不要求参不要求类类型,型,仅仅是符号是符号函数需事先函数需事先计计算算实实参表达式的参表达式的值值,再代入形参,再代入形参宏展开中不求表达式的宏展开中不求表达式的值值,,仅仅替替换换, 没有没有值传递值传递函数是在运行函数是在运行时处时处理理宏是在宏是在编译编译之前之前进进行行§带带参数的宏与函数的区参数的宏与函数的区别别函数函数调调用影响运行用影响运行时间时间,源程序无,源程序无变变化化宏展开影响宏展开影响编译时间编译时间,通常使源程序加,通常使源程序加长长函数函数调调用有一个返回用有一个返回值值 宏可以有多个宏可以有多个结结果果例例:求最大求最大值值。
答案中用答案中用U代表空格代表空格)#include
下找§ 说说明明 Ø 只包含源文件只包含源文件, ,不包含可不包含可执执行文件和目行文件和目标标文件Ø 可以嵌套可以嵌套例如例如: :需包含需包含file2.c,file2.c,包含包含,在,在file1file1中中, ,用两次用两次#include
程序““文件包含文件包含””示意示意图图 包含包含#include”file2.c” B A B A (a) (b) (c) 常用的有三种形式:常用的有三种形式: 形式一:形式一: #ifdef 宏名宏名 程序段程序段1;; #else 程序段程序段2;; #endif 或者:或者:#ifdef 宏名宏名 程序段;程序段;#endif 形式二:形式二: #ifndef 宏名宏名 程序段程序段1;; #else 程序段程序段2;; #endif其中,其中,# ifndef语语句的功能与句的功能与# ifdef相反,如果宏名相反,如果宏名未定未定义则编译义则编译程序段程序段1,否,否则编译则编译程序程序2。
或者:或者:#ifndef 宏名宏名 程序段;程序段;#endif形式三:形式三: #if 常数表达式常数表达式 程序段程序段1;; #else 程序段程序段2;; #endif 功功能能::首首先先计计算算“常常数数表表达达式式”的的值值,,如如果果为为真真((非非零零)),,就就编编译译“程程序序段段1”,,否否则则编编译译“程程序序段段2”如如果果没没有有#else部部分分,,则则当当“常常数数表表达达式式”的的值值为为0时时,,直接跳直接跳过过#endif或者:或者:#if 常数表达式常数表达式 程序段;程序段;#endif例:例:阅读阅读程序include
