c语言课件 第9章_预处理命令
C语言中级教材培训课程—预处理
C 语言中级培训预处理的概念编译前编译预处理器语言中,以“#”开头的语句统称为编译预处理命令。
以“#”开始,末尾这些命令必须在一行的开头以“#”开始,末尾不加分号,并且每条命令独占一行不加分号,并且每条命令独占一行,以区别于一为什么要用” 预处理”最小原则丁”的方式,由语言之外的预处理命令或函数提供。
就连处理预处理命令的预处理器C语言的预处理命令“预处理”前的预处理//有的系统是/ ,如VC++什么是宏#define PI (3.1415926)宏定义指令宏名字符串宏定义为什么要用宏定义-文字名称比数字要容易理解得多,一个好的宏名可以望文知义。
120使用宏的弊端:使用宏定义时需要注意的要点:宏替换的弊端:#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));多用括号就万事大吉了吗?2:在定义宏时不要为宏加分号。
#define assert(e)\续行符#define assert(e) \宏定义实例——无参宏定义举例宏定义实例——带参数的宏定义举例宏定义实例——用宏定义构建机制#ifdef AFXDLL #ifdef _AFXDLL{0000AfxSig end(AFX PMSG)0}\ {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \函数调用和宏定义的区别宏定义和类型定义的区别struct student*struct student *st uct stude t请分析下面语句的含义(*((UINT1*)(_data_)))定义了一个带参宏,它能将参数强转成无符号字符类型的地址,再将该地址中的值取出。
虎贲C语言第九章
9.1.1 不带参数的宏定义 所谓无参宏就是宏名后不带任何参数。其定义的一般形 式为: #define 宏名 字符串(或数值) 其中的“#”表示这是一条预处理命令, C语言中凡是以 “#”开头的命令都为预处理命令。 “define”为宏定义 命令。 说明: (1)宏名的前后应有空格。 (2)宏定义是用宏名来表示一个字符串,在宏展开时又 以该字符串取代宏名 。 (3)宏定义命令其后不要跟分号。 (4)字符串(或数值)中如果出现运算符号,则要注意 替换后的结果,通常可以在合适的位置加上括号。
第九章
预编译处理
____________ 虎贲讲师:路谨铭 ____________
章节知识点:
9.1 编译预处理 9.1.1 不带参数的宏定义 9.1.2 带参数的宏定义 9.1.3 带参数的宏和带参数的函数的区别 9.2 “文件包含”处理
笔试考点分布
知识点 不带参数的宏定义 带参数的宏定义 文件包含 所占分值 2分 2分 1分 考试概率 20% 60% 30% 难易程度
例9.5:求出下面程序段的结果!
#include<stdio.h> #define B(x) ((x)*(x)*(x)) */ /* 定义一个名为B的宏
main() { int i=1; while(i<=8) printf("%d\n",B(i++)); }
9.2 “文件包含”处理
文件包含命令的一般形式为: #include"文件名" 文件包含命令的功能是把指定的文件添加到预编译部分, 从而把指定的文件和当前的源程序文件进行连接。
(6)宏定义的嵌套使用 如: #define PI 3.1415926 #define R 5.5 #define CIRCLE 2.0* PI* R #define AREA PI* R * R (7)宏名的有效范围为从定义之处到本源文件结束。习惯上, #define写在程序最前面。 (8)宏名出现在一对双引号中,将不会产生置换 如:#define P 2.7189 main() { printf(“P=%d”, P); } 结果:P=2.7189
c语言预处理命令之条件编译(ifdefelseendifif等)
C语言预处理命令之条件编译(#ifdef,#else,#endif,#if等)预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。
可见预处理过程先于编译器对源代码进行处理。
在C语言中,并没有任何内在的机制来完成如下一些功能:在编译时包含其他源文件、定义宏、根据条件决定编译时是否包含某些代码。
要完成这些工作,就需要使用预处理程序。
尽管在目前绝大多数编译器都包含了预处理程序,但通常认为它们是独立于编译器的。
预处理过程读入源代码,检查包含预处理指令的语句和宏定义,并对源代码进行响应的转换。
预处理过程还会删除程序中的注释和多余的空白字符。
预处理指令是以#号开头的代码行。
#号必须是该行除了任何空白字符外的第一个字符。
#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。
整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。
下面是部分预处理指令:指令用途#空指令,无任何效果#include包含一个源代码文件#define定义宏#undef取消已定义的宏#if如果给定条件为真,则编译下面代码#ifdef如果宏已经定义,则编译下面代码#ifndef如果宏没有定义,则编译下面代码#elif如果前面的#if给定条件不为真,当前条件为真,则编译下面代码#endif结束一个#if……#else条件编译块#error停止编译并显示错误信息一、文件包含#include预处理指令的作用是在指令处展开被包含的文件。
包含可以是多重的,也就是说一个被包含的文件中还可以包含其他文件。
标准C编译器至少支持八重嵌套包含。
预处理过程不检查在转换单元中是否已经包含了某个文件并阻止对它的多次包含。
这样就可以在多次包含同一个头文件时,通过给定编译时的条件来达到不同的效果。
例如:#defineAAA#include"t.c"#undefAAA#include"t.c"为了避免那些只能包含一次的头文件被多次包含,可以在头文件中用编译时条件来进行控制。
C语言的预处理命令有哪些?
问:关于C语言中的预处理命令?答:我们可以在C源程序中插入传给编译程序的各种指令,这些指令被称为预处理器指令(等价于汇编语言中的伪指令),它们扩充了程序设计的环境。
现把常用的预处理命令总结如下:1. 预处理程序按照ANSI标准的定义,预处理程序应该处理以下12条指令:#if、#ifdef、#ifndef、#else、#elif、#endif、#define、#undef、#line、#error、#pragma、#include。
显然,所有的12个预处理指令都以符号#开始,,每条预处理指令必须独占一行。
2. #define#define指令定义一个标识符和一个串(也就是字符集),在源程序中发现该标识符时,都用该串替换之(原样替换,不要附加任何人为理解上的符号)。
这种标识符称为宏名字,相应的替换称为宏代换。
一般形式如下:#define macro-name char-sequence这种语句不用分号结尾。
宏名字和串之间可以有多个空格符,但串开始后只能以新行终止。
在C语言里宏定义只用来做的宏名替换,而不做语法检查的,因而它不是C语句,所以宏定义的语句结尾不需要加分号。
宏也在C里也叫预处理命令,因为宏是在程序编译前先进行字符替换的,所以叫预处理.例如:我们使用LEFT代表1,用RIGHT代表0,我们使用两个#define指令:#define LEFT 1#define RIGHT 0每当在源程序中遇到LEFT或RIGHT时,编译程序都用1或0替换。
定义一个宏名字之后,可以在其他宏定义中使用,例如:#define ONE 1#define TWO ONE+ONE#define THREE ONE+TWO宏代换就是用相关的串替代标识符。
因此,如果希望定义一条标准错误信息时,可以如下定义:#define ERROR_MS “Standard error on input \n”如果一个串长于一行,可在行尾用反斜线”\”续行,如下:#define LONG_STRING “This is a very very long \s tring that is used as an example”3. #error#error指令强制编译程序停止编译,它主要用于程序调试(放在错误的分支中,一旦进入错误的分支就显示该信息)。
c语言的预处理指令分3种 1宏定义 2条件编译 3文件包含
c语⾔的预处理指令分3种 1宏定义 2条件编译 3⽂件包含宏简介1.C语⾔在对源程序进⾏编译之前,会先对⼀些特殊的预处理指令作解释(⽐如之前使⽤的#include⽂件包含指令),产⽣⼀个新的源程序(这个过程称为编译预处理),之后再进⾏通常的编译所有的预处理指令都是以#开头,并且结尾不⽤分号2.预处理指令分3种 1> 宏定义 2> 条件编译 3> ⽂件包含3.预处理指令在代码翻译成0和1之前执⾏4.预处理的位置是随便写的5.预处理指令的作⽤域:从编写指令的那⼀⾏开始,⼀直到⽂件结尾,可以⽤#undef取消宏定义的作⽤6.宏名⼀般⽤⼤写或者以k开头,变量名⼀般⽤⼩写 宏定义可以分为2种:不带参数的宏定义和带参数的宏定义。
⼀、不带参数的宏定义1.⼀般形式#define 宏名字符串⽐如#define ABC 10右边的字符串也可以省略,⽐如#define ABC2.作⽤它的作⽤是在编译预处理时,将源程序中所有"宏名"替换成右边的"字符串",常⽤来定义常量.3.使⽤习惯与注意1> 宏名⼀般⽤⼤写字母,以便与变量名区别开来,但⽤⼩写也没有语法错误2> 对程序中⽤双引号扩起来的字符串内的字符,不进⾏宏的替换操作。
3> 在编译预处理⽤字符串替换宏名时,不作语法检查,只是简单的字符串替换。
只有在编译的时候才对已经展开宏名的源程序进⾏语法检查4> 宏名的有效范围是从定义位置到⽂件结束。
如果需要终⽌宏定义的作⽤域,可以⽤#undef命令5> 定义⼀个宏时可以引⽤已经定义的宏名#define R 3.0#define PI 3.14#define L 2*PI*R#define S PI*R*R举例1 #include <stdio.h>2#define COUNT 434int main()5 {6char *name = "COUNT";78 printf("%s\n", name);910int ages[COUNT] = {1, 2, 67, 89};1112#define kCount 41314for ( int i = 0; i<COUNT; i++) {15 printf("%d\n", ages[i]);16 }1718// 从这⾏开始,COUNT这个宏就失效19#undef COUNT2021//int a = COUNT 写这个报错2223return0;24 }⼆、带参数的宏定义1.⼀般形式#define 宏名(参数列表) 字符串2.作⽤在编译预处理时,将源程序中所有宏名替换成字符串,并且将字符串中的参数⽤宏名右边参数列表中的参数替换3.使⽤注意1> 宏名和参数列表之间不能有空格,否则空格后⾯的所有字符串都作为替换的字符串2> 带参数的宏在展开时,只作简单的字符和参数的替换,不进⾏任何计算操作。
预处理命令
二、表演区 (一)什么是表演区 表演区以幼儿表演游戏为设计核心,通过道具吸引幼儿积极参加故事表 演、游戏等活动。 (二)表演区的环境布置与材料投放 表演区可以分为固定式和活动式表演区角两类。 固定式的表演区角是指在活动室内辟出一定区域,存放表演所需要的用 具。 活动式的表演区角则是根据表演需要,临时在走廊、门厅、过道或室外 等地方设置表演场所,便于及时放置和收拢。
第9章 预处理命令
• 9. 1 概述 • 9. 2 宏定义 • 9. 3 文件包含 • 9. 4 条件编译
9. 2 宏定义
• 9. 2. 1 无参宏定义
• 无参宏的宏名后不带参数。 • 其定义的一般形式为 • #define 标识符字符串 • 其中, #表示这是一条预处理命令; 凡是以#开头的指令均为预处理命
果果:“老师,一分钟是多久呢?” 教师:“就是一会儿,我一转身。” 贝贝:“我知道,最细的秒针走一圈,挺长的。” 佳佳:“一分钟就是我们从门口走到后面的窗子那里。” 教师:“一分钟能做什么?” 佳佳:“给花浇水。” 果果:“唱完一首歌。” 贝贝:“搬来一把椅子。”……
学习目标
1. 了解幼儿日常交谈的主要特点及指导要求。 2. 掌握语言区角的环境布置与材料投放要求,能科学地开展语言区角活 动的指导。 3. 学会设计听说游戏的玩法,并能评析幼儿园听说游戏。
上一页 下一页 返回
9. 2 宏定义
• 【例9 - 2】不作宏代换程序举例。
上一页 下一页 说明: • 虽然已定义宏名OK 表示100, 但在printf 语句中OK 被引号括起来, 因
此不作宏代换。 • 程序的运行结果为“OK”, 这表示把“OK” 当字符串处理。
上一页 下一页 返回
义时, 必须十分注意, 应保证在宏代换之后不发生错误。
c语言教材第9章文件PPT教学课件
“w” ( 只 写 ) 为 输 出 打 开 一 文 本 文 件
“a” ( 追 加 ) 向 文 本 文 件 尾 加 数 据
“rb’ ( 只 读 ) 为 输 入 打 开 一 二 进 制 文 件
“wb” ( 只 写 ) 为 输 出 打 开 一 二 进 制 文 件
“ab” ( 追 加 ) 向 二 进 制 文 件 尾 加 数 据
运行结果:
test.txt 的内容是
3,4.50
} 2020/12/10
14
14
5. 文件定位
文件中有一个位置指针,指向当前读写的位置。 我们可以使用有关函数来改变其位置。
• 二进制文件:把内存中的数据按其在内存中的存 储形式原样输出到磁盘文件上。
4. 输入和输出方式
• 缓冲文件系统:系统自动在内存区为每一个正在
使用的文件名开辟一个缓冲区。从内存向磁盘输
出数据必须先送到内存的缓冲区中,装满缓冲区
后在一起送到磁盘中去。如果从磁盘向内存读入
数据,则一次从磁盘文件将一批数据
/* 文件操作模式 */ /* 下一个字符位置 */ /* 文件缓冲区位置 */
}FILE;
2020/12/10
7
7
2.文件类型指针
例: 定义一个FILE类型的数组
FILE -efile [-MAXFILE]; -MAXFILE: 数组元素个数,也就是可使用文件的
最大数目。
例:定义一个文件指针变量
“w b+ ’ ( 读 写 ) 为 读 /写 建 立 一 新 二 进 制 文 件
“ab+ ” ( 读 写 ) 为 读 /写 打 开 一 二 进 制 文 件
2020/12/10
11
11
C语言程序设计 第3版 第9章 编译预处理
#include "test2.c" static int sum(int n) {
int i,s=0; for(i=1;i<=n;i++)
s=s+fact(i); return s; }
static int fact(int n) {
C语言程序设计
第9章 编译预处理
第1讲:编译预处理基本形式
提纲
1.宏定义 2.文件包含 3.条件编译
1.宏定义
不带参数宏定义 带参数宏定义
格式:
#define 标识符 字符串
功能:
指定标识符代替一个较复杂的字符串。
注意说明:
(1)宏名一般习惯用大写字母,例如宏名PI。 (2)宏名用做代替一个字符串,不作语法检查。 (3)宏定义无需在末尾加“;” (4)宏定义的有效范围为#undef命令终止。 (5)在进行宏定义时,可以引用已定义的宏名。
char web[50]; int i=0; gets(web); while(web[i]!='\0') {
#if(R==1) if(web[i]>='A'&&web[i]<='Z') {web[i]=web[i]+32; i++;}
#else if(web[i]>='a'&&web[i]<='z') {web[i]=web[i]-32; i++;}
形式3:
#ifndef 标识符 程序段1
#else 程序段2
C语言的预处理程序与注释
C语言的预处理程序与注释C程序的源代码中可包括各种编译指令,这些指令称为预处理命令。
虽然它们实际上不是C语言的一部分,但却扩展了C程序设计的环境。
本节将介绍如何应用预处理程序和注释简化程序开发过程,并提高程序的可读性。
1、C语言的预处理程序ANSI标准定义的C语言预处理程序包括下列命令:#define #error #include #if#else #elif #endif #ifdef#ifndef #indef #line #pragma非常明显,所有预处理命令均以符号#开头,下面分别加以介绍。
2、#define命令#define定义了一个标识符及一个串。
在源程序中每次遇到该标识符时,均以定义的串代换它。
ANSI标准将标识符定义为宏名,将替换过程称为宏替换。
命令的一般形式为:#define identifier string注意,该语句没有分号。
在标识符和串之间可以有任意个空格,串一旦开始,仅由一新行结束。
例如,如希望TURE取值1,FALSE取值0,可说明两个宏#define#define TURE 1#define FALSE 0这使得在源程序中每次遇到TURE或FALSE就用0或1代替。
例如,在屏幕上打印“012”:printf("%d%d%d",FALSE,TRUE,TRUE+1);宏名定义后,即可成为其它宏名定义中的一部分。
例如,下面代码定义了O NE、TWO及THREE的值。
#define ONE 1#define TWO ONE+ONE#define THREE ONE+TWO懂得宏替换仅仅是以串代替标识符这点很重要。
因此,如果希望定义一个标准错误信息,可编写如下代码:#define E_MS "standard error on input\n"printf(E_MS);编译程序遇到标识符E_MS时,就用“standard error on input\n”替换。
第9章C语言
9.2.1 文件的打开
在C语言中,打开文件是由fopen()函数实现的,函数原型 如下: FILE *fopen( char *filename, char *mode ) 其中,filename和mode分别是所要打开文件的文件名和将要 对其操作的模式;函数的返回值是一个文件类型指针,指向 被打开文件的文件缓冲区(结构体变量)的起始地址。如果 文件打开失败,则函数返回值是一个NULL指针。 为了对已打开的文件进行操作,应该立即把fopen()函数 的返回值赋给一个文件类型指针变量,若没有立即把返回值 赋给一个文件类型指针,而进行其它操作,可能导致此函数 的返回值丢失,而无法对所打开的文件进行操作。 如果需要对磁盘文件file1.txt,进行读写操作,可用如下 方式打开这个文件:
9.3.1 输入和输出一个字符
(a)命令窗口中输入的命令 (b)读出的文件中的内容 图9-3 例9.1的执行结果
9.3.1 输入和输出一个字符
其中,“C Language!”是文件file1.txt中的内容。 需要注意的是,该程序是将打开文件中的字符,逐一 的取出并显示出来。直到遇到文件的结束标志,结束 读出操作。 可以通过该程序打开任意的文本文件,只要把所要打 开的文件名作为命令的参数即可。
9.1 文件概述
9.1.1 文件的基本概念 9.1.2 缓冲文件系统和非缓冲文件系统 9.1.3 文件类型指针
9.1.1 文件的基本概念
所谓文件是指记录在外部介质上的数据的集合。数据是 以文件的形式存放在外部介质上的。操作系统都是以文 件为单位对数据进行管理的,如果系统要从外部存储设 备上寻找需要的数据,系统首先找到该部分数据属于的 文件,根据文件名找到所指定的文件,然后从文件中读 出数据。如果要向外部存储设备上存储数据,也需要把 待存储的数据建立成文件,再以文件的形式向外输出。
C语言三种预处理功能
比如#define MAX(a,b) ((a)>(b)?(a):(b))则遇到 MAX(1+2,value)则会把它替换成: ((1+2)>(value)?(1+2):(value))注意事项和无参宏差不多。 但还是应注意
#define FUN(a) "a"
则,输入 FUN(345)会被替换成什么? 其实,如果这么写,无论宏的实参是什么,都不会影响其被替换成"a"的命运。也就是说, ""内的字符不被当成形参,即使它和一模一样。那么,你会问了,我要是想让这里输入 FUN(345)它就替换成"345"该怎么实现呢?请看下面关于#的用法
带参数
除了一般的字符串替换,还要做参数代换
格式: #define 宏名(参数表) 字符串
例如:
#define S(a,b) a*b area=S(3,2);//第一步被换为 area=a*b; ,第二步被换为 area=3*2;
(1)实参如果是表达式容易出问题
#define S(r) r*r area=S(a+b);//第一步换为 area=r*r;,第二步被换为 area=a+b*a+b;
值传递、返回值)。
冷门重点编辑
#define 用法
1、用无参宏定义一个简单的常量
#define LEN 12
这个是最常见的用法,但也会出错。比如下面几个知识点你会吗?可以看下:
(1)#define NAME "zhangyuncong" 程序中有"NAME"则,它会不会被替换呢? (2)#define 0x abcd 可以吗?也就是说,可不可以用不是标识符的字母替换成别的东 西? (3)#define NAME "zhang 这个可以吗? (4)#define NAME "zhangyuncong" 程序中有上面的宏定义,并且,程序里有句: NAMELIST 这样,会不会被替换成"zhangyuncong"LIST 四个题答案都是十分明确的。 第一个,""内的东西不会被宏替换。这一点应该大家都知道; 第二个,宏定义前面的那个必须是合法的用户标识符; 第三个,宏定义也不是说后面东西随便写,不能把字符串的两个""拆开; 第四个:只替换标识符,不替换别的东西。NAMELIST 整体是个标识符,而没有 NAME 标识符,所以不替换。 也就是说,这种情况下记住:#define 第一位置第二位置 (1) 不替换程序中字符串里的东西; (2) 第一位置只能是合法的标识符(可以是关键字); (3) 第二位置如果有字符串,必须把""配对; (4) 只替换与第一位置完全相同的标识符。 还有就是老生常谈的话:记住这是简单的替换而已,不要在中间计算结果,一定要替换出 表达式之后再算。
第9章预处理定义
C语言程序设计(第三版) My email:chenguot@
area=S(a); printf(“r=%f\narea=%f\n”,a,area);
area=3.1415926*a*a;
}
C语言程序设计(第三版) My email:chenguot@
10
§9.1 宏定义(7)
如下宏定义:
说明:
#define S (r) PI*r*r
⑴对带参数的宏的展开只是将语对句于中语的句宏名后面括号内的实
file1.c 或
file2.c
#include<file2.c>
#include <文件名> B
A
file1.c
A B
C语言程序设计(第三版) My email:chenguot@
16
§将包9.宏含2代到表用“文输户出程件格序包式中做:含出”头文处件理,并(2) (2)主文件file1.c
(好1处):将“格文式件宏包做含成”头命文令件可fo以rm节at.省h 程序设计void人m员ain的() 重复劳动。
#如inc:lud某e <单std位io.的h>人员往往使用一组固定的符号{ 常量(g=9.81,
#pdie=fi3n.e1P4R15p9ri2nt6f,e=2.718,c=…),可以把这些宏int定a,b义,c,d命; 令组成 ##一量定ddeeff个包义iinnee头含这ND文到些L“%“件自符\dn””,己号然所常后写量各的,人源相都文当可件于以中工用。业这上#in样的cl每标ud个准e命人零令cah=就件a1将r;b可,s=t这r2i以拿n;cg些=[不来]3=;符d“必就C=4号H;重用IN常A复。”;
Tc_12_tt_编译预处理
– 整个程序只允许有一个 整个程序只允许有一个main()函数 函数 当一个C 当一个C语言程序由多个文件模块组成时 整个程序只允许有一个main()函数. 函数. ,整个程序只允许有一个 函数 为了能调用写在其它文件模块中的函数, 为了能调用写在其它文件模块中的函数, 文件包含是一个有效的解决方法. 文件包含是一个有效的解决方法.
常用标准头文件
ctype.h 字符处理 math.h 与数学处理函数有关的说明与定义 stdio.h 输入输出函数中使用的有关说明和定义 string.h 字符串函数的有关说明和定义 stddef.h 定义某些常用内容 stdlib.h 杂项说明 time.h 支持系统时间函数
9.2 宏定义
area=S(3,2) ( , )
得 3*2
例9.3
#define PI 3.1415926 #define S(r) PI*r*r main() { float a,area; a=3.6; area=S(a); printf("r=%f\narea=%f\n",a,area); }
说 明
1. 注意宏定义时形参加括号的重要性.如对上例中的 注意宏定义时形参加括号的重要性. 宏定义,有下列语句: );,则宏展开为 宏定义,有下列语句:area=S(a+b);,则宏展开为: ( );,则宏展开为: area=PI*a+b*a+b;显然与程序设计者的意图不符. ;显然与程序设计者的意图不符. 正确的宏定义为: 正确的宏定义为: # define S(r) PI*(r)*(r) ( ) ( ) ( ) 2. 宏名与带参数的括号之间不能加空格. 宏名与带参数的括号之间不能加空格.
C语言初级学习——预处理命令
9.4 预定义宏
• 预定义宏是C编译器预先定义好的宏,不是 用户定义的,因而不能出现在#define与# undef语句中。 • 如: _ _FILE_ _ _ _DATE_ _ 等一些常见预定义宏标识符。
【例】预定义宏使用举例。
main() { printf("%s\n",__FILE__); printf("%s\n",__DATE__); printf("%s\n",__TIME__); }
结果显示: c:\data\a.c May 22 2001 21:02:54
9.5 运算符#和##
在带参数的宏替换中,若形参中含有#: • #:
“字符串” • 例如: #字符串 #define display(i) printf(#i) ……;display(This is a test);…… 则替换为:printf(“This is a test”);
若有宏定义:#define MOD(x,y) x%y
则执行以下语句后的输出为____
int z, a=15, b=100; z=MOD(b,a); printf(“%d\n”,z++); A 11 C 6 B 10 D 宏定义不合法
若有宏定义如下: #define x 5 #define Y X+1 #define Z Y*X/2 那么执行以下printf语句后,输出结果是____. int a; a=Y; printf(“%d\n”,Z); printf(“%d\n”,--a); A 7 B 12 C 12 D 7 6 6 5 5
#include “文件名称” #include <文件名称>
• 在一些版本的C语言中,还允许“文件名”中 带路径。
C语言预处理命令详解
C语⾔预处理命令详解⼀前⾔预处理(或称预编译)是指在进⾏编译的第⼀遍扫描(词法扫描和语法分析)之前所作的⼯作。
预处理指令指⽰在程序正式编译前就由编译器进⾏的操作,可放在程序中任何位置。
预处理是C语⾔的⼀个重要功能,它由预处理程序负责完成。
当对⼀个源⽂件进⾏编译时,系统将⾃动引⽤预处理程序对源程序中的预处理部分作处理,处理完毕⾃动进⼊对源程序的编译。
C语⾔提供多种预处理功能,主要处理#开始的预编译指令,如宏定义(#define)、⽂件包含(#include)、条件编译(#ifdef)等。
合理使⽤预处理功能编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计。
本⽂参考诸多资料,详细介绍常⽤的⼏种预处理功能。
因成⽂较早,资料来源⼤多已不可考,敬请谅解。
⼆宏定义C语⾔源程序中允许⽤⼀个标识符来表⽰⼀个字符串,称为“宏”。
被定义为宏的标识符称为“宏名”。
在编译预处理时,对程序中所有出现的宏名,都⽤宏定义中的字符串去代换,这称为宏替换或宏展开。
宏定义是由源程序中的宏定义命令完成的。
宏替换是由预处理程序⾃动完成的。
在C语⾔中,宏定义分为有参数和⽆参数两种。
下⾯分别讨论这两种宏的定义和调⽤。
2.1 ⽆参宏定义⽆参宏的宏名后不带参数。
其定义的⼀般形式为:#define 标识符字符串其中,“#”表⽰这是⼀条预处理命令(以#开头的均为预处理命令)。
“define”为宏定义命令。
“标识符”为符号常量,即宏名。
“字符串”可以是常数、表达式、格式串等。
宏定义⽤宏名来表⽰⼀个字符串,在宏展开时⼜以该字符串取代宏名。
这只是⼀种简单的⽂本替换,预处理程序对它不作任何检查。
如有错误,只能在编译已被宏展开后的源程序时发现。
注意理解宏替换中“换”的概念,即在对相关命令或语句的含义和功能作具体分析之前就要进⾏⽂本替换。
【例1】定义常量:1#define MAX_TIME 1000若在程序⾥⾯写if(time < MAX_TIME){.........},则编译器在处理该代码前会将MAX_TIME替换为1000。
二级c语言第九章预处理命令
如果在程序中有下面的语句: R1=Radium(100); 那么,在编译预处理时,宏展开的顺序为从左到右进行置换,如果字符串 中包含宏中的形参,则将其用程序语句中相应的实参来替代,而字符串中的 其它字符原样保留。 因此,在处理上述语句时,将用 sqrt(area/PI) 替代 Radium(100),同时将 字符串sqrt(area/PI)中的形参area用实参l00来替代,并把已定义的宏PI的值代 入,经宏展开后,该语句变为“ R1=sqrt(100/3.14159); ”。
内蒙古科技大学 工程训练中心
预处理命令概述
所谓预处理,就是指源程序被正式编译之前所进行的处理工作,这 是C语言和其他高级语言之间的一个重要区别。
所有的预处理指令均以“#”开头,在它前面不能出现空格以外的字 符,而且在行结尾处没有分号。 “预处理命令” 的作用不是实现程序的功能,它们是发布给编译系 统的信息。它们告诉编译系统,在对源程序进行编译之前应该做些什么, 所以称这类语句为编译预处理命令。 C语言在执行一个C程序时,如果程序中有预处理命令,则首先进行 编译预处理(即根据预处理命令对源程序进行预先处理),然后再将经过 预处理的源程序编译成目标文件,而后进行目标文件的连接,当这些工 作都顺利通过后,才最终执行目标代码。这种执行过程大大提高了编程 效率。
PI 的有效范围
因为#undef 的作用是终止宏定义,因此PI的作用域从它定义开始到 #undef结束。在这以后,如果程序中出现 PI,则它不代表3.14159 。使 用#undef可以灵活控制宏定义的作用范围。
2019年1月8日5时29分 工程训练中心 徐国海
(二)带参数宏定义 (了解) 定义的一般格式为: #define 宏名(形式参数列表) 字符串
C语言9
第 九 章 编 译 预 处 理
7-1
宏定义 不带参数的宏定义 带参数的宏定义
7-1-1 7-1-2
7-2
7-3
文件包含
条件编译
9-1
宏定义
例9-1 请看下面的程序: #define PI 3.14159 main() {float r,l,s; scanf("%f",&r); l=2*PI*r; s=PI*r*r; printf("l=%7.2f,s=%7.2f\n",l,s); } 程序的第一行内容:#define PI 3.14159 就是一个宏定义,PI 称为宏名,其作用是用标识符PI代表3.14159这样一串字符。在此之后 的程序中就可以用标识符PI代替3.14159,称为宏引用。 预处理时,程序中的PI 将被所定义的串3.14159替换,称为宏展开 或宏替换,如程序中的语句:l=2*PI*r;和s=PI*r*r;中的宏展开后分别 为:l=2*3.14159*r;和s=3.14159*r*r;。 有两种形式的宏 :不带参数的宏和带参数的宏。
9-2
文件包含(1)
一个C 程序由若干个源程序组成,而一个源文件还可以将另一个源 文件的全部内容包含进来,即将指定源文件的内容包含在当前文件中。 例如有两个源文件file1.c和file2.c,文件的内容分别如下: file1.c的内容: int max(int x,int y) {int z; if(x>y) z=x; else z=y; return z; } file2.c的内容: #include "file1.c" main() {int a,b,c; scan("%d,%d",&a,&b); c=max(a,b); printf("c=%d\n",c); }
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
17
带参数的宏和函数的区别: 带参数的宏和函数的区别:
(1) 函数调用时,先求出实参表达式的值,然后代入形 参。而使用带参的宏只是进行简单的字符替换。 (2) 函数调用是在程序运行时处理的,为形参分配临时 的内存单元。而宏展开则是在编译前进行的,在展 开时并不分配内存单元,不进行值的传递处理,也 没有“返回值”的概念。 (3) 对函数中的实参和形参类型要求一致。而宏名无类 型,它的参数也无类型,只是一个符号代表,展开 时代入指定的字符串即可。宏定义时,字符串可以 是任何类型的数据。 (4) 调用函数只可得到一个返回值,而用宏可以设法得 到几个结果。
6
使用不带参数的宏定义。 例9.1 使用不带参数的宏定义。
#include <stdio.h> #define PI 3.1415926 void 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\ns=%10.4f\nv=%10.4f\n",l,s,v); }
23
将例9 时格式宏做成头文件, 例9.6 将例9.5时格式宏做成头文件,把它 包含在用户程序中。 包含在用户程序中。 (2)主文件 主文件file1.c (2)主文件file1.c (1)将格式宏做成头文件 #include <stdio.h> (1)将格式宏做成头文件 #include "format.h" format.h void main() #include <stdio.h> { int a,b,c,d; #define PR printf char string[]="CHINA"; "\ #define NL "\n" a=1;b=2;c=3;d=4; #define D "%d" PR(D1,a); #define D1 D NL PR(D2,a,b); #define D2 D D NL PR(D3,a,b,c); #define D3 D D D NL PR(D4,a,b,c,d); #define D4 D D D D NL PR(S,string); #define S "%s" }
(7) 在进行宏定义时,可以引用已定义的宏名,可 以层层置换。
在宏定义中引用已定义的宏名。 例9.2 在宏定义中引用已定义的宏名。
#include <stdio.h> #define R 3.0 #define PI 3.1415926 #define L 2*PI*R #define S PI*R*R void main() { printf("L=%f\nS=%f\n",L,S); }
12
说明: 说明:
(8) 对程序中用双撇号括起来的字符串内的字符, 即使与宏名相同,也不进行置换。 (9) 宏定义是专门用于预处理命令的一个专用名词 ,它与定义变量的含义不同,只作字符替换,不 分配内存空间。
13
9.1.2 带参数的宏定义
作用:不是进行简单的字符串替换,还 要进行参数替换。 带参数的宏定义一般形式为:
19
对宏进行预编译,展开后的main函数如下: 对宏进行预编译,展开后的main函数如下: main函数如下
main() void main() { float r,l,s,v; scanf("%f",&r); l=2*3.1415926*r; s=3.1515926*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\ printf("r=%6.2f,l=%6.2f,s=%6.2f,v=%6.2f\n ",r,l,s,v); 运行情况如下: 运行情况如下: } 3.5↙ r=3.50,l=21.99,s=38.48,v=179.59
15
例9.3 使用带参的宏
运行情况如下: 运行情况如下:
#include <stdio.h> r=3.600000 #define PI 3.1415926 area=40.715038 #define S(r) PI*r*r void main() {float a,area; a=3.6; area=S(a); printf("r=%f\narea=%f\n",a,area); }
说明: 说明:
(1) 一个#include命令只能指定一个被包含文件, 如果要包含n个文件,要用n个#include命令。 (2) 如果文件1包含文件2,而在文件2中要用到 文件3的内容,则可在文件1中用两个include命 令分别包含文件2和文件3,而且文件3应出现 在文件2之前,即在file1.c中定义。 (3) 在一个被包含文件中又可以包含另一个被包含 文件,即文件包含是可以嵌套的。
4
基本概念
• C语言与其他高级语言的一个重要区别是可以 使用预处理命令和具有预处理的功能。 C提供的预处理功能主要有以下三种: 1.宏定义 2.文件包含 3.条件编译 这些功能分别用宏定义命令、文件包含命 令、条件编译命令来实现。为了与一般C语句 相区别,这些命令以符号“#”开头。例如: #define #include
9
#define G 9.8 _______ void main() ↑ { G的有效范围 … } -----↓---#undef G f1() f1函数中,G不再代表 函数中,G 在f1函数中,G不再代表 { 9.8。 9.8。这样可以灵活控制宏 … 定义的作用范围。 定义的作用范围。 }
10
说明: 说明:
第九章
本章要点
•预处理的概念 •C语言处理系统的预处理功能 •预处理命令的使用
主要内容
9.1 宏定义 9.2“文件包含” 9.2“文件包含”处理 9.3 条件编译
基本概念
• ANSI C标准规定可以在C源程序中加入一些“ 预处理命令” ,以改进程序设计环境,提高 编程效率。 • 这些预处理命令是由ANSI C统一规定的,但是 它不是C语言本身的组成部分,不能直接对它 们进行编译(因为编译程序不能识别它们)。 必须在对程序进行通常的编译之前,先对程序 中这些特殊的命令进行“预处理”。 • 经过预处理后程序可由编译程序对预处理后的 源程序进行通常的编译处理,得到可供执行的 目标代码。
宏名(参数表) #define 宏名(参数表) 字符串 字符串中包含在括弧中所指定的参数
例:
• 程序中用3和2分别代替宏 #define S(a,b) a*b 定义中的形式参数a和b, 用3*2代替S(3,2) 。因此 : 赋值语句展开为: area=S(3,2); area=3*2
14
对带参的宏定义是这样展开置换的: 对带参的宏定义是这样展开置换的:
1 12 123 1234 CHINA
22
9.2 “文件包含”处理 文件包含”
• 所谓“文件包含”处理是指一个源文件可以将另 外一个源文件的全部内容包含进来。C语言提供 了#include命令用来实现“文件包含”的操作。 其一般形式为: "文件名 文件名" #include "文件名" 或 #include <文件名> <文件名 文件名>
• 对带实参的宏(如S(3, 2),则按#define命令 行中指定的字符串从左到 右进行置换。若串中包含 宏中的形参(如a、b), 则将程序中相应的实参( 可以是常量、变量或表达 式)代替形参。如果宏定 义中的字符串中的字符不 是参数字符(如a*b中 的*号),则保留。这样 就形成了置换的字符串。
赋值语句“area=S(a); ” 经宏展开后为: area=3.1415926*a area=3.1415926*a*a;
16
说明: 说明:
(1)对带参数的宏展开只是将语句中的宏名后面 括号内的实参字符串代替#define 命令行 define 中的形参。 (2) 在宏定义时,在宏名与带参数的括弧之间不 应加空格,否则将空格以后的字符都作为替 代字符串的一部分。
20
带参数的宏和函数的区别: 带参数的宏和函数的区别:
(5) 不会使源 程序变长。 (6) 宏替换不占运行时间,只占编译时间。而函数 调用则占运行时间(分配单元、保留现场、值 传递、返回)。 如果善于利用宏定义,可以实现程序的 简化,如事先将程序中的“输出格式”定 义好,以减少在输出语句中每次都要写出 具体的输出格式的麻烦。
24
注意: 注意: 在编译时并不是分别对两个文件分别进行编 译,然后再将它们的目标程序连接的,而是 在经过编译预处理后将头文件format.h包含 到主文件中,得到一个新的源程序,然后对 这个文件进行编译,得到一个目标(.obj) 文件。被包含的文件成为新的源文件的一部 分,而单独生成目标文件。
25
21
通过宏展开得到若干个结果。 例9.5 通过宏展开得到若干个结果。
#include <stdio.h> void main() #define PR printf { int a,b,c,d; "\ #define NL "\n" char string[]="CHINA"; #define D "%d" a=1;b=2;c=3;d=4; #define D1 D NL PR(D1,a); #define D2 D D NL PR(D2,a,b); #define D3 D D D NL PR(D3,a,b,c); #define D4 D D D D NL PR(D4,a,b,c,d); #define S "%s" PR(S,string); } 运行时输出结果: