第8章 C语言编译预处理_第1页
第8章 C语言编译预处理_第2页
第8章 C语言编译预处理_第3页
第8章 C语言编译预处理_第4页
第8章 C语言编译预处理_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第八章编译预处理作用:对源程序编译之前做一些处理,生成扩展C源程序种类宏定义#define文件包含#include条件编译#if--#else--#endif等格式:“#”开头占单独书写行语句尾不加分号如if(x==YES)printf(“correct!\n”);elseif(x==NO)printf(“error!\n”);展开后:if(x==1)printf(“correct!\n”);elseif(x==0)printf(“error!\n”);8.1

宏定义8.1.1不带参数宏定义一般形式:#define宏名[宏体]功能:用指定标识符(宏名)代替字符序列(宏体)宏展开:预编译时,用宏体替换宏名---不作语法检查如#defineYES1#defineNO0#definePI3.1415926#defineOUTprintf(“Hello,World”);宏体可缺省,表示宏名定义过或取消宏体定义位置:任意(一般在函数外面)作用域:从定义命令到文件结束#undef可终止宏名作用域格式:

#undef

宏名例#defineYES1main(){……..}#undefYES#defineYES0max(){……..}YES原作用域YES新作用域宏定义可嵌套,不能递归例#defineMAXMAX+10(

)引号中的内容与宏名相同也不置换例#definePI3.14159printf(“2*PI=%f\n”,PI*2);宏展开:printf(“2*PI=%f\n”,3.14159*2);宏定义中使用必要的括号()例#defineWIDTH80#defineLENGTH

WIDTH+40

var=LENGTH*2;宏展开:var=80+40*2;()()例#defineWIDTH80#defineLENGTH

WIDTH+40

var=LENGTH*2;宏展开:var=80+40*2;

案例分析1(8.1)#definePRICE30main(){

int

num,total;num=10;total=num*PRICE;

printf(“total=%d”,total);}程序运算结果:total=300当价格发生变化时,只需要修改宏定义,就可以做到一改而全改案例分析2#definePI

3.1415926

main(){floatl,s,r,v;

printf("input

raDiuS∶");

scanf("%f",&r);

l=2.0*PI*r;

s=PI*r*r;

v=3.0/4*PI*r*r*r;

printf("l=%10.4f\nS=%10.4f\nv=%10.4f\n",l,s,v);}使用宏名代替一个字符串,可以用一个简单的名字来代替一个长的字符串。减少了程序中重复书写某些字符串的工作里昂,既不易出错,又提高了程序的可移植性。注意:如果字符串一行内装不下,可以放到下一行,只要在上一行的结尾处放一个反斜杠(\)即可。

例如:#defineLONG_STING“thisis\averylongstringthatisused.” 案例分析3#include<stdio.h>#define M 3#define N M+1#define NN N*N/2main(){printf(“%d\n”,NN);printf(“%d\n”,5*NN);}第一个printf的输出为6

第二个printf输出值为18

说明:#define命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到本源文件结束.

课堂练习8.1-7)、15)8.12带参数宏定义一般形式:#define宏名(参数表)宏体例#defineS(r)PI*r*r相当于定义了不带参宏S,代表字符串“(r)PI*r*r”宏展开:形参用实参换,其它字符保留宏体及各形参外一般应加括号()例#defineS(a,b)a*b………..area=S(3,2);宏展开:area=3*2;不能加空格例#definePOWER(x)x*xx=4;y=6;z=POWER(x+y);宏展开:z=x+y*x+y;一般写成:#definePOWER(x)((x)*(x))宏展开:z=((x+y)*(x+y));(1)程序中宏名后的实参与命令行中宏名后的虚参按位置一一对应。(2)用实参代替字符串中的虚参,注意只是字符串的代换,不含计算过程。(3)把用实参替换的字符串,替换程序中的宏名。[例8.3]写出下列程序运行的结果:

#definePT 3.5#defineS(x) PT*x*xmain()

{

inta=1,b=2;

printf(”%4.1f\n”,S(a+b));

}案例分析1说明:

(1)对带参数的宏的展开只是将语句中的宏名内的实参字符串代替#define命令行中的虚参,不能人为的增加括号和计算功能。(2)由子宏定义时,宏名与其所代替的字符串之间有一个或一个以上的空格。

#defineMAX(x,y)(x)>(y)?(x):(y)…….main(){inta,b,c,d,t;…….t=MAX(a+b,c+d);……}宏展开:t=(a+b)>(c+d)?(a+b):(c+d);int

max(int

x,inty){return(x>y?x:y);}main(){inta,b,c,d,t;…….t=max(a+b,c+d);………}例用宏定义和函数实现同样的功能<>案例分析2带参的宏与函数区别带参宏函数处理过程不分配内存简单的字符置换分配内存先求实参值,再代入形参处理时间编译时程序运行时参数类型无类型问题定义实参,形参类型程序长度变长不变运行速度不占运行时间调用和返回占时间<>课堂练习1

定义一个带参数的宏,使两个参数的值互换,并编一个程序,输入两个整数作为使用宏时的参数,输出已经交换的两个值。#defineSWAP(a,b) t=b;b=a;a=t;main(){

int

a,b,t;

printf(“请输入两个整数:”);

scanf(“%d,%d”,&a,&b);

printf(“\n原来得数据为:a=%d,b=%d\n”,a,b);

SWAP(a,b);

printf(“交换结果为:a=%d,b=&d\n”,a,b);}课堂练习2分析程序定义一个头文件“format.h”:在该文件中定义三种输出格式用户文件用#include语句将该文件包含起来;好处:避免重复工作;一改而全改;注意:宏定义修改后,序重新进行编译;8.2

文件包含功能:一个源文件可将另一个源文件的内容全部包含进来一般形式:#include“文件名”或#include<文件名>#include“file2.c”file1.cfile2.cfile1.cfile2.cABA处理过程:预编译时,用被包含文件的内容取代该预处理命令,再对“包含”后的文件作一个源文件编译<>直接按标准目录搜索“”先在当前目录搜索,再搜索标准目录可指定路径被包含文件内容源文件(*.c)头文件(*.h)宏定义数据结构定义函数说明等文件包含可嵌套#include“file2.c”file1.cAfile3.cC#include“file3.c”file2.c

Bfile1.cAfile3.cfile2.c文件包含的使用C语言标准库函数的使用#include<stdio.h>自己定义文件系统开发时,某单位人员往往使用一组固定的符号常量,可以把这些宏定义组成一个文件,然后每人都可以使用#include命令把这些符号常量包含到自己的程序中,从而避免重复工作;此外可做到一改而全改;案例分析

[例8.7]头文件应用实例(1)文件print_format.h#definePRprintf#defineNL“\n”#defineD“%d”#defineD1DNL#defineD2DDNL#defineD3DDDNL#defineD4DDDDNL#defineS“%s”(2)文件file1.c#include”print_format.h”main(){int

a,b,c,d;charstring[]=“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,sting);}8.3条件编译C语言也允许有选择的对源程序的某一部分进行编译,这就是“条件编译”。

条件编译有以下三种形式:#ifdef<标识符>

程序段1#else

程序段2#endif#ifndef<标识符>

程序段1#else

程序段2#endif#if表达式程序段1#else

程序段2#endif#ifdef<标识符>

程序段1#else

程序段2#endif8.3.1条件编译语句1它的功能是:当指定标识符已经被定义过(一般用#define命令定义),则对程序段1进行编译,否则对程序段2进行编译。

案例分析1条件编译对于提高C源程序的通用性是很有好处的。如果一个C源程序在不同计算机系统上运行,而不同的计算机又有一定的差异(例如,有的机器以16位(2个字节)来存放一个整数,而有的则以32位存放一个整数),这样往往需要对源程序作必要的修改,这就降低了程序的通用性。可以用以下的条件编译来处理:#ifdef

COMPUTER-A#define

INTEGER-SIZE16#else#define

INTEGER-SIZE32#endif即如果COMPUTER-A在前面已被定义过,则编译下面的命令行:#defineINTEGER-SIZE16否则,编译下面的命令行:#defineINTEGER-SIZE32案例分析2例如,在调试程序时,常常希望输出一些所需的信息,而在调试完成后不再输出这些信息。可以在源程序中插入以下的条件编译段:#ifdefDEBUGprintf("x=%D,y=%D,Z=%D\n",x,y,Z);#endif如果在它的前面有以下命令行:#defineDEBUG则在程序运行时输出x、y、Z的值,以便调试时分析。8.3.2条件编译语句2

#ifndef<标识符>

程序段1#else

程序段2#endif它的功能是:若指定的标识符未被定义则编译程序段1,否则编译程序段2。这种形式的功能和第一种形式的功能相反。

例如:

#ifndefLIST

printf("x=%d,y=%d,z=%d\n",x,y,z);

#endif其预处理功能为:如在此之前未对LIST定义,则输出x,y,z的值。在程序调试时,不对LIST定义,此时输出x,y,z的值,调试结束后,在运行上述程序段之前,加以下面的命令行:

#define LIST则不输出x,y,z的值。8.3.3条件编译语句3#if表达式程序段1#else

程序段2#endif

它的功能是:当指定的表达式为真(非零)时.编译程序段1,否则编译程序段2。应用这种条件编译的方法,可以事先给定某一条件:使程序在不同的条件下执行不同的功能。案例分析

[例8.8]用条件编译方法实现以下功能:

输入一行电报文字,可以任选两种输出,一为原文输出;一为将字母变成其下一字母(如‘a’变成’b’,…,’z’变成‘a’,其它字符不变)。用#define命令来控制是否要译成密码。例如:

#defineCHANGE1

则输出密码。若

#defineCHANGE0

则不译成密码,按原码输出。#include<stdio.h>#defineMAX80#defineCHANGE1main(){charstr[MAX];

inti;

printf(“请输入文本行:\n”);

scanf(“%s”,str);

#if(CHANGE){for(i=0;i<MAX;i++) {

if(str[i]!=’\0’)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论