第九章 预处理命令
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include “file2.c” B A file2.c file1.c file1.c A
file2.c
包含文件的查找方法:
#include “文件名 ” 先在当前工作目录中去查找,若找不到再到指定
的标准目录中去查找。
#include <文件名>
直接到系统指定的标准目录中去查找。
如:对Turbo C编译系统,先在用户目录下查 找,然后在TC\include文件夹中查找。 如:对VC 6.0编译系统,直接在C:\Program Files\Microsoft Visual Studio\VC98\Include 文件夹中查找。
void main() { int a,b,c,d; char string[]="CHINA"; a=1;b=2;c=3;d=4; PR(D1,a); PR(D2,a,b); PR(D3,a,b,c); PR(D4,a,b,c,d); PR(S,string); } 运行结果: 1 12 123 1234 CHINA
宏展开:预编译时,用宏体替换宏名---不作语法检查
注意:
引号中的内容与宏名相同也不置换
例 #define PI 3.14159 printf(“2*PI=%f\n”,PI*2); 宏展开:printf(“2*PI=%f\n”,3.14159*2);
宏定义中使用必要的括号() 例 #define WIDTH 80 #define LENGTH (WIDTH+40) var=LENGTH*2; 宏展开:var= (80+40) *2;
例1: #ifdef TURBO #define int int #else #define int short #endif
可用于实现程序 在不同环境下的 兼容性。
例2:
#ifdef DEBUG 可用于进行程序 的调试。
printf(“x=%d,y=%d\n”,x,y); #endif 调试过程中,在程序前面加#define DEBUG 调试完成后,将前面的#define DEBUG删除掉
例9.1 使用不带参数的宏定义 #include <stdio.h> 运行: input radius: 4 #define PI 3.1415926 l=25.1328 void main() s=50.2655 { float l,s,r,v; v=150.7966 printf("input radius : "); scanf("%f",&r); l=2.0*PI*r; s=PI*r*r; v=4.0/3.0*PI*r*r*r; printf("l=%10.4f\ns=%10.4f\nv=%10.4f\n",l,s,v); }
9.2 “文件包含”处理 <> 直接按标准目录搜索 功能:一个源文件可将另一个源文件的内容全部包含 “ ” 先在当前目录搜索,再搜索标准目录 进来 可指定路径 一般形式: #include “文件名” 或 #include <文件名> 处理过程:预编译时,用被包含文件的内容取代该预处 理命令,再将“包含”后的文件作为一个源文件单位 进行编译,得目标文件.obj
形式二:
# ifdef 标识符 程序段1 #endif
作用:当所指定的标识 符已经被#define 命令定 义过,则在程序编译阶 段只编译程序段1,
形式三:
# ifndef 标识符 程序段1 # else 程序段2 #endif 作用:当所指定的标识 符未被#define 命令定义 过,则在程序编译阶段 只编译程序段1,否则编 译程序段2。
本 章 小 结
(1) C语言的宏定义可以分为两种形式:一种是带参 数的宏定义;另一种是不带参数的宏定义。 (2)所谓文件包含预处理,是指在一个文件中将另外 一个文件的全部内容包含进来的处理过程,即将 另外的文件包含到本文件中。 (3)一般情况下,源程序中所有的行都参加编译。但 是有时希望对其中一部分内容只有在满足一定条 件下才进行编译,也就是对一部分内容指定编译 的条件,这就是“条件编译”。
例:输入一个口令,根据需要设置条件编译,使之在调试程序 时,按原码输出;在使用时输出“*”号。 #define DEBUG void main() { char pass[80];int i=1; printf("\nplease input password:"); do{i++; pass[i]=getchar(); #ifdef DEBUG putchar(pass[i]); #else putchar('*'); #endif } while(pass[i]!='\r'); …… }
定义的一般形式为: #if 表达式1 程序段1 #elif表达式2 程序段2 #elif表达式3 程序段3 ……
#else 程序段n #endif 这里的#elif的含义是“else if”。
程序举例:用同一程序实现大小写字母转换( 若定义UP转换为大写)
#include
"stdio.h" #define UP main() { char s[128]; gets(s); #ifdef UP strupr(s); #else strlwr(s); #endif puts(s); }
C语言程序设计
杨秋格 灾害信息工程系
第九章
预处理命令
主要内容
一、宏定义 #define #include 二、“文件包含”处理
三、条件编译 #if #else #endif
9.1 宏定义
宏定义命令
(1)不带参数的宏定义 一般形式: #define 标识符
宏体可缺省,表示宏名 定义过或取消宏体
字符串
例9.5 用宏代表输出格式 #include <stdio.h> #define PR printf #define NL "\n" #define D "%d" #define D1 D NL #define D2 D D NL #define D3 D D D NL #define D4 D D D D NL #define S "%s"
注意: 宏替换后,程序的原意表达。
#define PF(x) x*x /*#define PF(x) (x)*(x) */ /*#define PF(x) ((x)*(x)) */ main() 注意替换时不求值, { 只是字符串的原样替换 int a=2, b=3, c; c=PF(a+b)/PF(a+1); printf("\nc=%d ",c); } 按第一种宏定义:c=a+b*a+b/a+1*a+1;
按第二种宏定义:c=(a+b)*(a+b)/(a+1)*(a+1);
按第三种宏定义:c=((a+b)*(a+b))/((a+1)*(a+1));
带参数的宏替换与函数的主要区别
⑴函数调用时,先求出实参表达式的值,然后代入形参。而使 用带参的宏只是进行简单的字符替换。 ⑵函数调用是在程序运行时处理的,分配临时的内存单元。而 宏替换则是在编译时进行的,在展开时并不分配内存单元, 不进行值的传递处理,也没有“返回值”的概念。 ⑶宏替换不占运行时间,只占编译时间,而函数调用则占运行 时间。 ⑷函数中函数名及参数均有一定的数据类型,而宏不存在类型 问题,宏名及其参数无类型。
例9.4 使用宏带回几个结果 #include <stdio.h> #define PI 3.1415926 #define CIRCLE(R,L,S,V) L=2*PI*R;S=PI*R*R; V=4.0/3.0*PI*R*R*R void main() { float r,l,s,v; scanf("%f",&r); CIRCLE(r,l,s,v); printf("r=%6.2f,l=%6.2f,s=%6.2f,v=%6.2f\n",r,l,s,v); } 宏展开后: 运行: void main() 3.5 { float r,l,s,v; r=3.50,l=21.99,s=38.48,v=179.59 scanf("%f",&r); l=2*3.1415926*r;s=3.1415926*r*r;v=4.0/3.0*3.1415926*r*r*r; printf("r=%6.2f,l=%6.2f,s=%6.2f,v=%6.2f\n",r,l,s,v);}
二、使用常量表达式的值作为编译条件
形式: #if 表达式 程序段1 #else 程序段2 #endif
作用:当所指定的表达 式为真(非零)时就编 译程序段1,否则编译程 序段2。
可以事先给定一定条件,使程序在不 同的条件下执行不同的功能。
注意:#if和#endif必须配对使用。
带有#elif的条件编译
运行结果: 1 12 123 1234 CHINA
⑵ 主文件file1.c #include <stdio.h> #include "format.h" void main() { int a,b,c,d; char string[]="CHINA"; a=1;b=2;c=3;d=4; PR(D1,a); PR(D2,a,b); PR(D3,a,b,c); PR(D4,a,b,c,d); PR(S,string); }
例9.6 将例9.5改为文件包含 ⑴ 格式宏做成头文件format.h #define PR printf #define NL "\n" #define D "%d" #define D1 D NL #define D2 D D NL #define D3 D D D NL #define D4 D D D D NL #define S "%s"
(2)带参数的宏定义 一般形式: #define 宏名(参数表) 宏体
功能:进行字符串替换,并进行参数替换 例 #define S(a,b) a*b ……….. 不能加空格 area=S(3,2); 宏展开: area=3*2; 宏展开:形参用实参换,其它字符保留 宏体及各形参外一般应加括号() 例 #define 例 #define SPOWER(x) x*x (r) PI*r*r x=4; y=6; 相当于定义了不带参宏S,代表字符串“(r) PI*r*r” z=POWER(x+y); 宏展开:z=x+y*x+y; 一般写成: #define POWER(x) ((x)*(x)) 宏展开: z=((x+y)*(x+y));
功能:用指定标识符(宏名)代替字符串序列(宏体)
如 #define 例YES 1 #define YES 1 #define NO 0 main() #define PI …….. { 3.1415926 YES原作用域 #define OUT printf(“Hello,World”); } #undef YES 定义位置:任意(一般在函数外面) #define YES 0 作用域:从定义命令到文件结束 max() YES新作用域 {…….. #undef可终止宏名作用域 } 格式: #undef 宏名
§9.3 条件编译 条件编译:根据条件选择被编译的源程序行。
•使用宏定义的标识符作为编译条件 •使用常量表达式的ifdef 标识符 程序段1 # else 程序段2 #endif
作用:当所指定的标识符已 经被#define 命令定义过, 则在程序编译阶段只编译程 序段1,否则编译程序段2。
file2.c
包含文件的查找方法:
#include “文件名 ” 先在当前工作目录中去查找,若找不到再到指定
的标准目录中去查找。
#include <文件名>
直接到系统指定的标准目录中去查找。
如:对Turbo C编译系统,先在用户目录下查 找,然后在TC\include文件夹中查找。 如:对VC 6.0编译系统,直接在C:\Program Files\Microsoft Visual Studio\VC98\Include 文件夹中查找。
void main() { int a,b,c,d; char string[]="CHINA"; a=1;b=2;c=3;d=4; PR(D1,a); PR(D2,a,b); PR(D3,a,b,c); PR(D4,a,b,c,d); PR(S,string); } 运行结果: 1 12 123 1234 CHINA
宏展开:预编译时,用宏体替换宏名---不作语法检查
注意:
引号中的内容与宏名相同也不置换
例 #define PI 3.14159 printf(“2*PI=%f\n”,PI*2); 宏展开:printf(“2*PI=%f\n”,3.14159*2);
宏定义中使用必要的括号() 例 #define WIDTH 80 #define LENGTH (WIDTH+40) var=LENGTH*2; 宏展开:var= (80+40) *2;
例1: #ifdef TURBO #define int int #else #define int short #endif
可用于实现程序 在不同环境下的 兼容性。
例2:
#ifdef DEBUG 可用于进行程序 的调试。
printf(“x=%d,y=%d\n”,x,y); #endif 调试过程中,在程序前面加#define DEBUG 调试完成后,将前面的#define DEBUG删除掉
例9.1 使用不带参数的宏定义 #include <stdio.h> 运行: input radius: 4 #define PI 3.1415926 l=25.1328 void main() s=50.2655 { float l,s,r,v; v=150.7966 printf("input radius : "); scanf("%f",&r); l=2.0*PI*r; s=PI*r*r; v=4.0/3.0*PI*r*r*r; printf("l=%10.4f\ns=%10.4f\nv=%10.4f\n",l,s,v); }
9.2 “文件包含”处理 <> 直接按标准目录搜索 功能:一个源文件可将另一个源文件的内容全部包含 “ ” 先在当前目录搜索,再搜索标准目录 进来 可指定路径 一般形式: #include “文件名” 或 #include <文件名> 处理过程:预编译时,用被包含文件的内容取代该预处 理命令,再将“包含”后的文件作为一个源文件单位 进行编译,得目标文件.obj
形式二:
# ifdef 标识符 程序段1 #endif
作用:当所指定的标识 符已经被#define 命令定 义过,则在程序编译阶 段只编译程序段1,
形式三:
# ifndef 标识符 程序段1 # else 程序段2 #endif 作用:当所指定的标识 符未被#define 命令定义 过,则在程序编译阶段 只编译程序段1,否则编 译程序段2。
本 章 小 结
(1) C语言的宏定义可以分为两种形式:一种是带参 数的宏定义;另一种是不带参数的宏定义。 (2)所谓文件包含预处理,是指在一个文件中将另外 一个文件的全部内容包含进来的处理过程,即将 另外的文件包含到本文件中。 (3)一般情况下,源程序中所有的行都参加编译。但 是有时希望对其中一部分内容只有在满足一定条 件下才进行编译,也就是对一部分内容指定编译 的条件,这就是“条件编译”。
例:输入一个口令,根据需要设置条件编译,使之在调试程序 时,按原码输出;在使用时输出“*”号。 #define DEBUG void main() { char pass[80];int i=1; printf("\nplease input password:"); do{i++; pass[i]=getchar(); #ifdef DEBUG putchar(pass[i]); #else putchar('*'); #endif } while(pass[i]!='\r'); …… }
定义的一般形式为: #if 表达式1 程序段1 #elif表达式2 程序段2 #elif表达式3 程序段3 ……
#else 程序段n #endif 这里的#elif的含义是“else if”。
程序举例:用同一程序实现大小写字母转换( 若定义UP转换为大写)
#include
"stdio.h" #define UP main() { char s[128]; gets(s); #ifdef UP strupr(s); #else strlwr(s); #endif puts(s); }
C语言程序设计
杨秋格 灾害信息工程系
第九章
预处理命令
主要内容
一、宏定义 #define #include 二、“文件包含”处理
三、条件编译 #if #else #endif
9.1 宏定义
宏定义命令
(1)不带参数的宏定义 一般形式: #define 标识符
宏体可缺省,表示宏名 定义过或取消宏体
字符串
例9.5 用宏代表输出格式 #include <stdio.h> #define PR printf #define NL "\n" #define D "%d" #define D1 D NL #define D2 D D NL #define D3 D D D NL #define D4 D D D D NL #define S "%s"
注意: 宏替换后,程序的原意表达。
#define PF(x) x*x /*#define PF(x) (x)*(x) */ /*#define PF(x) ((x)*(x)) */ main() 注意替换时不求值, { 只是字符串的原样替换 int a=2, b=3, c; c=PF(a+b)/PF(a+1); printf("\nc=%d ",c); } 按第一种宏定义:c=a+b*a+b/a+1*a+1;
按第二种宏定义:c=(a+b)*(a+b)/(a+1)*(a+1);
按第三种宏定义:c=((a+b)*(a+b))/((a+1)*(a+1));
带参数的宏替换与函数的主要区别
⑴函数调用时,先求出实参表达式的值,然后代入形参。而使 用带参的宏只是进行简单的字符替换。 ⑵函数调用是在程序运行时处理的,分配临时的内存单元。而 宏替换则是在编译时进行的,在展开时并不分配内存单元, 不进行值的传递处理,也没有“返回值”的概念。 ⑶宏替换不占运行时间,只占编译时间,而函数调用则占运行 时间。 ⑷函数中函数名及参数均有一定的数据类型,而宏不存在类型 问题,宏名及其参数无类型。
例9.4 使用宏带回几个结果 #include <stdio.h> #define PI 3.1415926 #define CIRCLE(R,L,S,V) L=2*PI*R;S=PI*R*R; V=4.0/3.0*PI*R*R*R void main() { float r,l,s,v; scanf("%f",&r); CIRCLE(r,l,s,v); printf("r=%6.2f,l=%6.2f,s=%6.2f,v=%6.2f\n",r,l,s,v); } 宏展开后: 运行: void main() 3.5 { float r,l,s,v; r=3.50,l=21.99,s=38.48,v=179.59 scanf("%f",&r); l=2*3.1415926*r;s=3.1415926*r*r;v=4.0/3.0*3.1415926*r*r*r; printf("r=%6.2f,l=%6.2f,s=%6.2f,v=%6.2f\n",r,l,s,v);}
二、使用常量表达式的值作为编译条件
形式: #if 表达式 程序段1 #else 程序段2 #endif
作用:当所指定的表达 式为真(非零)时就编 译程序段1,否则编译程 序段2。
可以事先给定一定条件,使程序在不 同的条件下执行不同的功能。
注意:#if和#endif必须配对使用。
带有#elif的条件编译
运行结果: 1 12 123 1234 CHINA
⑵ 主文件file1.c #include <stdio.h> #include "format.h" void main() { int a,b,c,d; char string[]="CHINA"; a=1;b=2;c=3;d=4; PR(D1,a); PR(D2,a,b); PR(D3,a,b,c); PR(D4,a,b,c,d); PR(S,string); }
例9.6 将例9.5改为文件包含 ⑴ 格式宏做成头文件format.h #define PR printf #define NL "\n" #define D "%d" #define D1 D NL #define D2 D D NL #define D3 D D D NL #define D4 D D D D NL #define S "%s"
(2)带参数的宏定义 一般形式: #define 宏名(参数表) 宏体
功能:进行字符串替换,并进行参数替换 例 #define S(a,b) a*b ……….. 不能加空格 area=S(3,2); 宏展开: area=3*2; 宏展开:形参用实参换,其它字符保留 宏体及各形参外一般应加括号() 例 #define 例 #define SPOWER(x) x*x (r) PI*r*r x=4; y=6; 相当于定义了不带参宏S,代表字符串“(r) PI*r*r” z=POWER(x+y); 宏展开:z=x+y*x+y; 一般写成: #define POWER(x) ((x)*(x)) 宏展开: z=((x+y)*(x+y));
功能:用指定标识符(宏名)代替字符串序列(宏体)
如 #define 例YES 1 #define YES 1 #define NO 0 main() #define PI …….. { 3.1415926 YES原作用域 #define OUT printf(“Hello,World”); } #undef YES 定义位置:任意(一般在函数外面) #define YES 0 作用域:从定义命令到文件结束 max() YES新作用域 {…….. #undef可终止宏名作用域 } 格式: #undef 宏名
§9.3 条件编译 条件编译:根据条件选择被编译的源程序行。
•使用宏定义的标识符作为编译条件 •使用常量表达式的ifdef 标识符 程序段1 # else 程序段2 #endif
作用:当所指定的标识符已 经被#define 命令定义过, 则在程序编译阶段只编译程 序段1,否则编译程序段2。