计算机程序设计c语言第09章预处理命令

合集下载

c语言学习资料第9章 预处理命令.doc

c语言学习资料第9章 预处理命令.doc

第9章预处理命令宏定义不是c语句,所以不能在行尾加分号。

如果加了分号则会连分号一起进行置换。

可以用#undef命令终止宏定义的作用域。

对程序中用""括起来的内容(即字符串内的字符),即使与宏名相同,也不进行置换。

宏定义只做字符替换,不分配内存空间。

宏名不是变量,不分配存储空间,也不能对其进行赋值。

在宏展开时,预处理程序仅对宏名作简单的字符串替换,不作任何检查。

在进行宏定义时,可以引用已定义的宏名无参宏定义的一般格式:#define 标识符字符串将这个标识符(名字)称为“宏名”,在用预编译时将宏名替换成字符串的过程称为"宏展开"。

#define是宏定义命令。

带参宏定义的一般格式:#define 宏名(形参表)字符串带参宏的调用和宏展开:调用格式:宏名(实参表);宏展开(又称为宏替换)的方法:用宏调用提供的实参直接置换宏定义中相应的形参,非形参字符保持不变。

定义有参宏时,宏名与左圆括号之间不能留有空格。

否则,C编译系统会将空格以后的所有字符均作为替代字符串,而将该宏视为无参宏。

有参宏的展开只是将实参作为字符串,简单地置换形参字符串而不做任何语法检查。

为了避免出错,可以在所有形参外,甚至整个字符串外,均加上一对圆括号。

如:#define S(r) 3.14*(r)*(r)则:areapS(a^b); 展开后为:area^ 3.14*(a^ b)*(cH- b);调用有参函数时,是先求出实参的值,然后再复制一份给形参。

而展开有参宏时,只是将实参简单地置换形参。

函数调用是在程序运行时处理的,为形参分配临时的内存单元;而宏展开则是在编译前进行的,在展开时不分配内存单元,不进行值的传递,也没有’返回值"的概念。

调用函数只可得到一个返回值,而用宏可以设法得到几个结果。

在有参函数中,形参都是有类型的,所以要求实参的类型与其一致;而在有参宏中,形参和宏名都没有类型,只是一个简单的符号代表,因此,宏定义时,字符串可以是任何类型的数据。

C语言程序设计 第9章 预处理命令

C语言程序设计 第9章 预处理命令

区别“文件名”和<文件名> --关于#include的使用
#include “文件名” #include <文件名> 带双引号的文件名, 带尖括号的文件名, 系统将先在源程序所在 系统将直接按照指定 的目录内查找指定的包 的标准方式到相关的 含文件;如果找不到, 目录中去寻找。 再按照系统指定的标准 方式到相关的目录中去 寻找。 多用于包含用户文件。 多用于标准库函数。
答案:8 20 12

5、设有以下程序,为使之正确运行,请填 入应包含的命令行。其中,tryme()函数在 a:\myfile1.c 中有定义。
#include “a:\myfile1.c” ___________________ main() { printf(“\n”); tryme(); }
9.3 条件编译
格式一: #ifdef 标识符
#ifdef 标识符
程序段1
程序段1
#else
#endif
程序段2
#endif
格式二:
格式三:
#ifndef 标识符
程序段1 #else 程序段2 #endif
#if 表达式
程序段1 #else 程序段2 #endif
课堂练习:
1、以下叙述中不正确的是: (A)预处理命令行都必须以#号开始 (B)C程序中凡是以#开始的命令行都是预处理命 令行 (C)C程序在执行过程中对预处理命令进行预处理 (D)以下是正确的宏定义 #define IBM_PC

File Edit Run Compile Project Options Debug Break/watch ╒═══════════════════════════ │ Compiler │ │ │ Linker │ │ │ Environment │ │ │ Directories │ │ ┌──────────────────── │ │ Include directories: C:\TC\INCLUDE │ │ Library directories: C:\TC\LIB │ Output directory: D:\CDATA │ │ Turbo C directory: C:\TC │ │ Pick file name: │ │ Current pick file:

第9章:预处理命令

第9章:预处理命令

7、宏定义时,可以引用已定义的宏 名,可以层层置换。
例9.2 # define R 3.0
# define PI 3.1415926 # define L 2*PI*R # define S PI*R*R main( ) {printf(“L=%f \n S=%f \n”,L,S); } printf函数展开为:
对宏定义的9点说明: 对宏定义的9点说明:
1、宏名一般习惯用大写字母表示。 2、用宏名代替一个字符串,可以减少程 序中重复书写某些字符串的工作量。当需要 改变某一个常量的值时,只改变宏定义命令 行即可。例: #define M 20 float str[M]; 3、宏定义是用宏名代替一个字符串,也 就是作简单的替换,不作正确性检查。即使 写错了,预处理时也照样带入。只有在编译 已被宏展开的源程序时才报错。
文件包含” 9.2 “文件包含”处理 文件包含
“文件包含”处理是指一个源文件可以将另 外一个源文件的全部内容包含进来。 C语言提供了#include命令,用来实现“文件 包含”的操作。一般形式为: file1.c # include “文件名” 文件名” 文件名 file1.c file2.c
# include “file2.c” A
例 9.1 p.188
# define PI 3.1415926 main( ) {float l, s, r ,v ; printf(“input radius :”) ; scanf(“%f”,&r); l=2.0 * PI * r ; s=PI * r * r ; v=4.0/3 * PI * r * r * r ; printf(“l=%10.4f\n s=%10.4f\n v=%10.4f\n”,l,s,v) ; }

第9章 预处理命令

第9章  预处理命令
可缺省,表示宏名 可缺省, 定义过或取消宏体
第 十 章
预 处 理 命 令
后面的单词串 容文本 #define SIZE 10 如 #define YES 1 #define INT_STR "%d" void main ( ) #define NO 0 void main ( ) { #define PI 3.1415926 { int a[10], i; a[10], 宏定义 #define OUT printf(“Hello,World”); int a[SIZE], i; a[SIZE], for (i = 0; i < 10; i++) 10; for (i = 0; i < SIZE; i++) SIZE; scanf ("%d", &a[i]); ("%d", scanf (INT_STR, &a[i]); (INT_STR, 预编译 for (i = 10 - 1; i >= 0; i--) i--) for (i = SIZE - 1; i >= 0; i--) i--) 处理后 printf ("%d", a[i]); ("%d", printf (INT_STR, a[i]); (INT_STR, } }
a = 3.14; * 2 * 2;
错误! 错误!
第 十 章
预 处 理 命 令
{ N的内容是10 的内容是10 #define NUM2 20 { return (N * N); #define NUM (NUM1 + NUM2) int a = 2, b = 3; } void main ( ) a *= ( + 20) ; 10 { b = b * ( + 20) ; 10 //第二次宏定义 int a = #define N 20 //第二次宏定义 2, b = 3; printf ("a = %d, b = %d\n", a, b); %d\ void a *= NUM; main ( ) NUM; } { N的内容是20 的内容是20 b = b * NUM; NUM; printf ("%d%d\ N + f )); ("%d\n", \ printf ("a = %d, b = %d\n", a, (b); 预编译 输出结果: 输出结果: } 处理后 } a = 60, b = 50 90

第九章 预处理命令

第九章 预处理命令
C语言程序设计 - 第6章 预处理
12
(3) 在调用函数时,对使用的实参有一 在调用函数时, 定的数据类型限制; 定的数据类型限制;而带参的宏的实 可以是任意数据类型。 参,可以是任意数据类型。 (4) 函数调用时,存在着从实参向形参 函数调用时, 传递数据的过程, 传递数据的过程,而带参数的宏不存在 这种过程。 这种过程。
说明
宏定义仅是把参数作为字符串做简单替换, 宏定义仅是把参数作为字符串做简单替换, 而不做任何运算求值和语法检查 宏名与参数表的括号之间不应有空格 应注意参数替换后可能出现的语法错误和意 料之外的运算 应在宏定义内容及其中参数两边加上括号
C语言程序设计 - 第6章 预处理 10
带参宏定义举例
#define S1(a,b) a*b #define S2(a,b) ((a)*(b)) #define max(a,b) ((a)>(b)?(a):(b)) ((a)>(b)?(a):(b)) int main() { int x=3, y=4, i=5, j=6, s, z; s=S1(x+y, x-y); /* s=x+y*x-y; s==11 */ xs=x+y*xs=S2(x+y, x-y); /* s=((x+y)*(x-y)); s==-7 */ xs=((x+y)*(xs==z=max(i++, j++); /* z=((i++)>(j++)?(i++):(j++)); */ z=((i++)>(j++)?(i++):(j++)); /* z==7, i==6, j==8 */ }

c语言程序设计第九章预处理命令

c语言程序设计第九章预处理命令
(1)一个include命令只能指定一个被包含文件,如果要包含 n个文件,要用n个include命令。
(2)如果文件1包含文件2,而文件2中要用到文件3的内容,则 可在文件1中用两个include命令分别包含文件 2和文件3, 而且文件3应出现在文件2之前,即在 filel.c中定义: #include “file3.h” #include “file2.h”
(4)宏定义不是C语句,不必在行末加分号。如果加了分号则 会连分号一起进行置换。如:
#define PI 3.1415926; area=PI* r* r;
经过宏展开后,该语句为 area= 3.1415926;* r* r ; 显然出现语法错误。
(5)#define命令出现在程序中函数的外面,宏名的有效范围 为定义命令之后到本源文件结束。通常, #define命令写 在文件开头,函数之前,作为文件一部分,在此文件范围 内有效。
运行情况如下: input radius:4 l=25.1328 s=50.2655 v=150.7966
2、说明:
(1)宏名一般习惯用大写字母表示,以便与变量名相区别。 (2)使用宏名代替一个字符串,可以减少程序中重复书写某
些字符串的工作量。
(3)宏定义是用宏名代替一个字符串,也就是作简单的置换, 不作正确性检查。
(6)可以用#undef命令终止宏定义的作用城。例如:
# define G 9.8
main()
{ ...
}
# undef G
进行宏定义时,可以引用已定义的宏名,可以层层 置换。
例2 分析下面程序的运行结果
#define R 3.0 #define PI 3.1415926 #define L 2*PI*R #define S PI*R*R main() {

第九章 预处理命令

第九章 预处理命令

思考题1:执行下面程序后, 的值为多少 的值为多少? 思考题 :执行下面程序后,a的值为多少? #define SP(x) x*x main() { int a,k=2; a=SP(k); printf("%d\n",a); } 宏展开后为: 宏展开后为:a=k*k;
思考题2:执行下面程序后, 的值为多少? 思考题 :执行下面程序后,area的值为多少? 的值为多少 #define PI 3.1415926 #define S(r) PI*r*r main() { float a,b,area; a=2.6;b=2.4; area=S(a+b); printf("%f\n",area); } 宏展开后为: 宏展开后为:area=3.1415926*a+b*a+b; 16.8081 而不是: 而不是:area=3.1415926*(a+b)*(a+b); 78.5398
说明: 说明:
1) 定义带参数的宏时,宏名和后面的括号之间不能有 定义带参数的宏时, 空格,否则连空格一起作为字符串的一部分。 空格,否则连空格一起作为字符串的一部分。 2) 带参数的宏定义与函数不同: 带参数的宏定义 函数不同 宏定义与 不同: (1) 带参数的宏不考虑参数的类型,如果实参是表达 带参数的宏不考虑参数的类型, 不考虑参数的类型 也不求表达式的值,只是简单的字符串替换。 式,也不求表达式的值,只是简单的字符串替换。 宏展开是在预处理时进行的,在展开时, 宏展开是在预处理时进行的,在展开时,不分配存 储单元,也不进行值的传递。 储单元,也不进行值的传递。 函数调用是在程序运行时执行的 调用是在程序运行时执行的, (2) 函数调用是在程序运行时执行的,需要考虑参数 的类型,如果实参是表达式,需先求表达式的值, 的类型,如果实参是表达式,需先求表达式的值, 再进行参数传递。 再进行参数传递。

c语言 ●第9章 预处理命令

c语言 ●第9章 预处理命令
16
三、说明 1.要包含几个文件,就用几个 .要包含几个文件,就用几个#include。 。 2.可嵌套包含。 .可嵌套包含。 file1.c file2.c
#include <file2.c> …… #include <file3.c> ……
file3.c
没有文件包含 ……
等价于: 等价于:file1.c
2
输入半径,求圆的周长、圆的面积、球体积。 例9.1 输入半径,求圆的周长、圆的面积、球体积。 #include <stdio.h> #define PI 3.14159 void main() { float r,l,s,v; printf("r=?"); scanf("%f",&r); l=2*PI*r; s=PI*r*r; v=4.0/3.0*PI*r*r*r; printf("l=%.4f,s=%.4f,v=%.4f\n例9.4 利用宏展开得到若干个结果
#include <stdio.h> #define PI 3.14159 #define CIRCLE(R,L,S,V) L=2*PI*R; S=PI*R*R; V=4.0/3*PI*R*R*R void main() { float r,l,s,v; printf("r=?"); scanf("%f",&r); CIRCLE(r,l,s,v); /* 设r=2.0 */ /* l=2*3.14159*2.0;s=3.14159*2.0*2.0; */ /* v=4.0/3*3.14159*2.0*2.0*2.0; */ printf("r=%.2f,l=%.2f,s=%.2f,v=%.2f\n",r,l,s,v); } 结果:r=3.50,l=21.49,s=38.48,v=179.59 结果:
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

10
② 定义有参宏时,宏名与左圆括号之间不能留有空格。否 则,C编译系统将空格以后的所有字符均作为替代字符 串,而将该宏视为无参宏。
2014-11-16
一、宏定义
有参宏与有参函数比较
11
① 调用有参函数时,是先求出实参值,然后再代入形参。而展 开有参宏时,只是将实参简单地置换形参。 ② 调用有参函数,在程序运行时处理,为形参分配临时的 内存单元。而宏展开在编译前进行,不分配内存单元, 不进行值传递,不返回值。 ③ 函数无论调用多少次,都不会使目标程序变长,但每次 调用都要占用系统时间进行调用现场保护和现场恢复; 宏展开不占运行时间,但是每引用1次,都会使目标程序 增大1次。 2014-11-16
2014-11-16
三、条件编译
3. #if 表达式 程序段1; [#else 程序段2;] #endif
19
功能:当表达式为非0(“逻辑真”)时,编译程序 段1,否则编译程序段2。
2014-11-16
小结
20
宏定义 “文件包含”处理 条件编译
2014-11-16
作 业
作 业:9-2,9-3 上机:9-6

P207 例9.3
2014-11-16
一、宏定义
说明
① 有参宏的展开,只是将实参作为字符串,简单地置 换形参字符串,而不做任何语法检查。
若定义:#define S(r) PI*r*r 则语句:area=S(a+b) 替换后为area=PI*a+b*a+b 要得到area=PI*(a+b)*(a+b),需定义为: #define S(r) PI*(r)*(r)
21
思考题:
一般程序在什么情况下使用宏定义?
2014-11-16
一、宏定义
有参宏与有参函数比较
12
④ 在有参函数中,形参是有类型的,而且要求实参的类型与 其一致;而在有参宏中,形参没有类型信息,只是一个符 号代表,因此可以是任何类型。 ⑤ 函数调用只能得到一个返回值,而用宏可以设法得到几 个结果。
2014-11-16
二、文件包含
文件包含:一个源文件可以将另一个源文件的全部内容包含 进来。 格式: #include “包含文件名” 或 #include <包含文件名> ■ 两种格式的区别在于: ① 使用双引号:系统首先到当前目录下查找被包含文件,如果没 找到,再到系统指定的“包含文件目录”(由用户在配置环境 时设置)去查找。 ② 使用尖括号:直接到系统指定的“包含文件目录”去查找。一 般地说,使用双引号比较保险。
2014-11-16
一、宏定义
说明
① 宏名一般用大写字母表示,以便与变量区别。 ② 在宏展开时,预处理程序仅以按宏定义简单替换宏 名,而不作任何检查。如果有错误,只能由编译程 序在编译宏展开后的源程序时发现。
6
③ 宏定义不是C语句,所以不能在行尾加分号。否则, 宏展开时,会将分号作为字符串的1个字符,用于 替换宏名。 2014-11-16
14
2014-11-16
二、文件包含
说明:
15
① 一条包含命令,只能指定一个被包含文件。如果要包含n 个文件,则要用n条包含命令。 ② 编译预处理时,预处理程序将查找指定的被包含文件, 并将其复制到#include命令出现的位置上。
③ 文件包含可以嵌套,即被包含文件中又包含另一个文件。
2014-11-16
2014-11-16
一、宏定义
例:输入圆的半径,求圆的周长、面积和球的体积。要 求使用无参宏定义圆周率。
#include<stdio.h> #define PI 3.1415926
/*PI是宏名,3.1415926用来 替换宏名的 常数*/
5
void main() { float r,l,s,v; printf("Input a r: "); scanf("%f",&r); l=2*PI*r; /*引用无参宏求周长*/ s=PI*r*r; /*引用无参宏求面积*/ v=PI*r*r*r*3/4; /*引用无参宏求体积*/ printf("length=%.2f,area=%.2f,volume=%.2f\n", l, s, v); }
三、条件编译
条件编译:程序中一部分内容只在满足一定条 件时才进行编译,即对这一部分内容指定编译 的条件
16
作用:可有效地提高程序的可移植性,并广泛 地应用在商业软件中,为一个程序提供各种不 同的版本。
2014-11-16
三、条件编译
1. #ifdef 标识符 程序段1; [#else 程序段2;] #endif
① ② ③ C提供的预处理功能: 宏定义 文件包含 条件编译
3
2014-11-16
一、宏定义
1. 不带参数的宏定义 #define 标识符 字符串
4
① “define”为宏定义命令;
② “标识符”为所定义的宏名,通常用大写字母表 示,以便于与变量区别;
③ “字符串”可以是常数、表达式、格式串等。当 是一个常量时,则相应的“宏名”就是一个符号
件包含
文件包含的优点:
一个大程序,通常分为多个模块,并由多个程序 员分别编程。有了文件包含处理功能,就可以将多个 模块共用的数据(如符号常量和数据结构)或函数, 集中到一个单独的文件中。这样,凡是要使用其中数 据或调用其中函数的程序员,只要使用文件包含处理 功能,将所需文件包含进来即可,不必再重复定义它 们,从而减少重复劳动。
17
功能:当“标识符”已经被#define命令定义过,则 编译程序段1,否则编译程序段2。
2014-11-16
三、条件编译
2. #ifndef 标识符 程序段1; [#else 程序段2;] #endif
18
功能:与第一种形式的作用相反,若“标识符”未被 #define命令定义过,则编译程序段1,否则编译程序 段2。
第九章
预处理命令
主要任务: 1.掌握宏定义的用法; 2.了解文件包含的概念; 3.熟练掌握文件包含命令include的用法; 4.了解条件编译的概念
主要内容
2
宏定义 “文件包含”处理 条件编译
2014-11-16
预处理命令
编译预处理:在对源程序进行编译之前,先对源程序中 的编译预处理命令进行处理;然后再将处理的结果,和 源程序一起进行编译,以得到目标代码。
一、宏定义
说明
④ 宏定义命令#define出现在函数的外部,宏名的有 效范围是:从定义命令之后, 到本文件结束。通 常,宏定义命令放在文件开头处。 ⑤ 可以用#undef命令终止宏定义的作用域
7
⑥ 在进行宏定义时,可以引用已定义的宏名 。
2014-11-16
一、宏定义
说明
⑦ 对双引号括起来的字符串内的字符,即使与宏名同 名,也不进行宏展开。 ⑧ 宏定义只作字符替换,不分配内存空间
8
使用宏定义的优点
① 可提高源程序的可维护性 ② 可提高源程序的可移植性 ③ 减少源程序中重复书写字符串的工作量
2014-11-16
一、宏定义
2. 带参数的宏定义 #define 宏名(形式参数表) 字符串

9
调用格式:宏名(实参表) 宏展开:用宏调用提供的实参字符串,直接置换 宏定义命令行中相应形参字符串,非形参字符保 持不变。
相关文档
最新文档