大一上c语言编译预处理tianme_第1页
大一上c语言编译预处理tianme_第2页
大一上c语言编译预处理tianme_第3页
大一上c语言编译预处理tianme_第4页
大一上c语言编译预处理tianme_第5页
已阅读5页,还剩35页未读 继续免费阅读

下载本文档

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

文档简介

第十一部分编译预处理preprocessing一、编译预处理简介在编译之前,对高级语言程序的源代码进行的加工,生成编译器能处理的代码的过程。C语言源程序编译目标模块连接可执行程序函数库C程序加工过程编译之前还有一个源代码预加工的过程有预处理命令的C源程序编译目标模块连接可执行程序函数库C程序加工过程包含有编译前的预处理的功能预处理没有预处理命令的C源程序最先做的步骤,预处理程序负责处理源程序里的所有预处理命令,生成不含预处理命令的源程序。预处理命令—加在程序中指示IDE的预处理程序进行代码处理工作的指令。预处理命令作用:简化编程工作C预处理命令C源程序中以字符#开始的命令即为预处理命令常见的预处理命令有#include#if#else#elif#endif#ifdef#ifndef#define#undef问题:为什么叫命令?命令谁做事情?二、C的文件包含#include7把指定文件内容包含到当前源文件#include<文件名> 形式1#include"文件名" 形式2形式1:用于包含系统头文件,预处理程序到指定目录找文件(通常指定几个系统文件目录)。Tools->Options->Directories->C:\ProgramFiles\MicrosoftVisualStudio\VC98\INCLUDEC:\ProgramFiles\MicrosoftVisualStudio\VC98\MFC\INCLUDEC:\ProgramFiles\MicrosoftVisualStudio\VC98\ATL\INCLUDE1.文件包含命令语法形式2:用于包含自己的文件。预处理程序先在源文件所在的目录里找,找不到时再到系统指定目录中去找。8在文件系统中查找指定的文件如果找到,就用找到的文件的内容取代整个文件包含命令行。被包含文件里如果也有预处理行也会嵌套处理。2.预处理过程#include“abc.h”……doublearea(doubler){returnPI*r*r;}abc.cpp在操作系统文件系统中寻找头文件如果找到,用相应的头文件里的内容替代包含命令。doublearea(doubler);intfunc2();voidfunc3();enum{YES,NO};#definePI3.14159继续处理abc.h文件包含处理过程及示例doublearea(doubler);intfunc2();voidfunc3();enum{YES,NO};#definePI3.14159……doublearea(doubler){returnPI*r*r;}处理后的abc.cpp10stdio.h或math.h为标准头文件(.h扩展名),它们在系统子目录里(目录名为include或h),这些文件中的内容一般包括标准函数原型系统使用的符号常量定义等。预处理时,文件内容插入到预处理命令行处。相当于在源文件中写这些函数原型,使编译程序能正确完成对标准库函数调用的处理。#include<stdio.h>#include<math.h>注意:写程序时一定要包含必要的系统头文件。说明三、宏定义与宏替换#define#undef12简单宏定义,形式:

#define宏名字替代正文替代正文可以是任意正文序列,到换行为止。如最后是“\”,下一行还作为宏定义的继续。作用:为宏名字定义替代,由整个替代正文构成。预处理程序记录宏名字及其替代。在源程序中遇到宏名字标识符时,就用替代正文替换,这种操作称为宏展开或宏替换。1.常见宏定义与宏替换注意替代正文里也允许出现宏名字,替代正文里宏名字会被展开。程序中的字符串如果有与宏名相同的串,将不会做替换。人们常用这种方式定义符号常量。#defineNUM3014#defineNUM30#defineSLDstaticlongdouble#defineNOSTOPwhile(1)程序中的:SLDx=2.4,y=9.16;替换后变成:staticlongdoublex=2.4,y=9.16;后无;预处理程序做正文替换,替代正文可以是任何内容。例,可以写如下形式的定义#defineNOSTOPwhile(1)#include“abc.h”……doublearea(doubler){returnPI*r*r;}abc.cppdoublearea(doubler);intfunc2();voidfunc3();enum{YES,NO};#definePI3.14159abc.h宏定义及宏替换doublearea(doubler);intfunc2();voidfunc3();enum{YES,NO};#definePI3.14159……doublearea(doubler){returnPI*r*r;}包含后的abc.cppdoublearea(doubler);intfunc2();voidfunc3();enum{YES,NO};……doublearea(doubler){return3.14159*r*r;}宏替换后的abc.cpp2.带参数宏定义(慎用)#define宏名字(参数列表)替代正文注意宏名字与括号间不能有空格用逗号分隔的标识符看作参数。替换正文为任意正文序列。例#defineMIN(A,B)((A)<(B)?(A):(B))也被人称为Pseudo-functions,假函数,伪函数带参宏的使用使用形式与函数调用类似,以类似参数的形式给出宏参数的替代片段,用逗号分隔多个数,称为宏调用。例x=MIN(y,z);预处理器对源代码中的宏调用的宏替换(宏展开)过程分两步展开先用各实参替代宏定义替代正文里的参数;再将代换的结果放在宏调用位置(因此并非函数调用)带参宏与函数调用不同带参宏只是在程序预加工阶段对用户写的源代码进行处理,按带参宏的展开规划处理程序源代码,与函数调用完全不同。不会在程序执行阶段产生与函数一样的调用动作。因为只做字符串替换,宏定义和调用中不涉及类型问题。一个宏能否使用、使用中发生什么、能否得到预期效果,完全看展开后的情况。带参宏的效率与限制Preprocessorfunctions,whichareusuallycalledmacrosorpseudo-functions,areconsiderablymoreefficientthatstandardCfunctionsbutalsomorerestrictive.Efficient:不是函数调用,省去函数调用与返回所需的时间与空间开销Restrictive:不是函数调用,仅是替换,不具有函数的灵活性,只适合非常简单的小功能。不小心会带来许多注意不到问题例,带参宏定义与展开#defineMIN(A,B)((A)<(B)?(A):(B))为什么加括号?z=MIN(x+y,x*y);z=(x+y)<(x*y)?(x+y):(x*y));宏替换预处理前的源代码预处理后的程序代码看上去像是函数调用,是吗?根本不是函数调用使用括号避免出错替代正文各参数和整段应括起,避免出错。例如#defineSQUARE(x)x*x在特定环境下可能出问题,例如z=SQUARE(a+b);展开后变成z=a+b*a+b;明显错了慎重使用宏展开注意,宏展开可能会引起多次计算带来意外的很难发现的错误,要慎重使用#defineMIN(A,B)((A)<(B)?(A):(B))z=((n++)<(m++)?(n++):(m++));宏替换预处理前的源代码预处理后的程序代码z=MIN(n++,m++);3.宏名字定义#define标识符定义一个标识符,告诉预编译器定义了这样的名字。通过判定是否存在某宏名,配合#if,#ifdef,#ifndef等实现一些特定编译预处理目的如设LabFunctions.h中有如下代码#ifndefLABFUNCTIONS_H_#defineLABFUNCTIONS_H_…#endif判定是否曾定义过LABFUNCTIONS_H_如果没有定义过,则定义一个这样的标识符目的:避免头文件的重复包含以免产生问题4.#undef与defined宏定义可以取消,语法#undef宏名字功能:取消已有宏名字定义特殊谓词defined,使用形式defined标识符defined(标识符)当标识符是有定义的宏名字时,defined(标识符)得到1,否则得05.说明带参宏的展开可避免函数调用开销,但将使最终的源程序变长。复杂宏定义展开后出错很难定位。应谨慎使用(尽量少使用)宏。写宏定义的常见错误是在定义行最后写分号。该分号将被代入程序,有可能引起语法错误。宏定义从定义处起作用直到文件结束。一个文件里不允许对同一宏名字重复定义。261.宏名一般都用大写字母表示,以区别于变量;2.宏定义只是替代,减少了在程序中书写的工作量,只是一个简单的代替,不作语法检查;3.宏定义不是语句,不必再其后加上“;”;4.在宏定义中可以进行多层的替代.#definreR 3.0#definePI 3.1415#defineL 2*PI*R#defineS PI*R*Rmain()

{printf(“L=%f\nS=%f\n”,L,S);}27例#include<stdio.h>#definePI3.1415#defineS(r)PI*r*rintmain(){doublea,area;a=3.6;area=S(a);printf(“r=%f\narea=%f\n”,a,area);return0;}28例#include<stdio.h>#defineM 3#defineN M+2#defineS(N)N*N*Nintmain(){ printf("%d\n",S(N)); return0;}运行结果为:17四、条件编译命令30条件编译一、引入条件编译的原因:只对源程序中满足条件的部分内容进行编译。可以减少被编译的语句,从而减少目标程序的长度。二、定义形式:31程序段可以是语句串,也可以是命令行方式3为嵌套定义方式2:#if整型表达式程序段1#else程序段2#endif方式1:#if整型表达式程序段1#endif方式3:#if整型表达式程序段1#elif整型表达式

程序段2#elif整型表达式

程序段3……#else程序段n#endif32#ifdef标识符 相当于#ifdefined(标识符)#ifndef标识符相当于#if!defined(标识符)方式4:#ifdef标识符程序段1#else程序段2#endif方式5:#ifndef标识符程序段1#else程序段2#endif33#defineCOMPUTER_A1#ifdefCOMPUTER_A#defineINTEGER_SIZE16#else#defineINTEGER_SIZE20#endif#defineDEBUG1#ifdefDEBUGprintf(“x=%d,y=%d,z=%d\n”,x,y,z);#endif

预处理后只剩下#defineINTEGER_SIZE16参与编译预处理后printf参与编译,若不在希望编译printf得到输出,则删除#defineDEBUG1命令行。34例#defineLETTER1intmain(){charc;inti=0;while((c=getchar())!=‘\n’){i++;#ifdefLETTERif(c>=‘a’&&c<=‘z’)c=c-32;#elseif(c>=‘A’&&c<=‘Z’)c=c+32;#endifprintf(“%c”,c);}

温馨提示

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

最新文档

评论

0/150

提交评论