《c程序 预处理与程序组织设计》由会员分享,可在线阅读,更多相关《c程序 预处理与程序组织设计(24页珍藏版)》请在金锄头文库上搜索。
1、预处理命令与程序组 织 学习目标l lC C语言的预处理命令,宏替换的使用方法语言的预处理命令,宏替换的使用方法l l程序的组织方式程序的组织方式课程内容l l1 1 概述概述 l l2 2 #define #define定义宏定义宏 l l3 3 预定义宏预定义宏 l l4 4 #include #include包含包含 l l5 5 条件编译条件编译 l l6 6 程序组织程序组织n预处理指在进行编译的第一遍扫描(词法扫描和语法分析 )之前所作的工作。n预处理是C语言的一个重要功能,它由预处 理程序负责完成。当对一个源文件进行编译 时,系统将自动引用预处理程序对源程序中 的预处理部分作处理
2、,处理完毕自动进入对 源程序的编译。1概述源文件源文件 * *.c.c运行文件运行文件 * *.exe.exe编译编译编译编译编译编译目标文件目标文件 * *. .objobj连接连接编译编译连接连接连接连接编译预处理编译预处理 编编 译译n编译预处理包括:n 宏定义n 文件包含n 条件编译分别用宏定义命令、文件包含命令、条件编译命令来实现。 为了与一般C语句相区别,这些命令以符号“#”开头。源文件源文件 * *.c.c运行文件运行文件 * *.exe.exe目标文件目标文件 * *. .objobj编译编译连接连接main()main() float float r,s,cr,s,c; ;s
3、canf(“%f”,);s = r * r * s = r * r * 3.143.14; ;c = 2 * r * c = 2 * r * 3.143.14; ;printf(“sprintf(“s=%f, c=%=%f, c=%f”,s,cf”,s,c);); 如何修改圆周率2 #define定义宏n宏定义的功能:在源程序中每次遇到宏名 时,均以定义的串代换它。这个替换过程称 为“宏代换”或“宏展开” n宏定义的形式:n宏取消:#define 宏名 字符串#undef 宏名如果被取消的宏实际上没有被 #define所定义,针对它的#undef并 不会产生错误。当一个宏定义被取 消后,可以再
4、度定义它。n源程序:n#define PI 3.14n#define S PI*r*rn#define V 4*S*r/3nmain( )nfloat r;n printf(“nInput r:“);n scanf(“%f“,n printf(“S=%.2f V=%.2fn“,S,V);n编译预处理后的程序: main( ) float r;printf(“nInput r:“);scanf(“%f“,printf(“S=%.2f V=%.2fn“,3.14*r*r, 4* 3.14*r*r *r/3); SVSV进入编译进入编译n宏代换不是函数。与函数的区别:简单置换,与调用函数不同,次数多
5、时使程序变 长,而函数调用不使程序变长。宏展开在编译时进行,占用编译时间,不占运行 时间,不进行值的传递处理,无返回值;函数占 运行时间。宏是简单置换,没有返回值;函数有返回值。不定义形参类型,无类型。n宏特点:替换需要注意替换时可能引起的优先级问题。最好的 办法就是将宏的参数直接用括号括起来。【例11.1】创建一个求两个数中较大数的宏1#define Max(value1,value2) (value1value2) ? value1:value2 2void main() 3 4int iVar1=3, iVar2=8; 5float fVar1=3.5, fVar2=10.6; 6dou
6、ble dVar1=10.0, dVar2=100.0; 7printf(“Two integers compare:n“); 8printf(“Max(%d,%d)=%dn“,iVar1,iVar2,Max(iVar1,iVar2); 9printf(“Two floats compare:n“); 10printf(“Max(%f,%f)=%fn“,fVar1,fVar2,Max(fVar1,fVar2); 11printf(“Two doubles compare:n“); 12printf(“Max(%f,%f)=%fn“,dVar1,dVar2,Max(dVar1,dVar2); 1
7、3 运行结果如下: Two integers compare: Max(3,8)=8 Two floats compare: Max(3.500000,10.600000)=10.600000 Two doubles compare: Max(10.000000,100.000000)=100.000000宏定义参数没有设置类型 当宏定义超过1行时,使用连接符(即反斜杆“” 【例11.2】超过1行的宏1int func_swap(int A,int B) 2 3int temp; 4temp=A; 5A=B; 6B=temp; 7return temp; 89#define SWAP(A, B
8、, TYPE) 10 11TYPE temp = A;12A = B;13B = temp; 14 函数定义宏定义15 void main() 16 17int iVar1=10,iVar2=20; 18printf(“Before func_swap: iVar1=%d, iVar2=%dn“, iVar1, iVar2); 19func_swap(iVar1, iVar2); 20printf(“After func_swap: iVar1=%d, iVar2=%dn“, iVar1, iVar2); 21printf(“Before SWAP: iVar1=%d, iVar2=%dn“,
9、 iVar1, iVar2); 22SWAP(iVar1, iVar2, int); 23printf(“After SWAP: iVar1=%d, iVar2=%dn“, iVar1, iVar2); 24 运行结果如下: Before func_swap: iVar1=10, iVar2=20 After func_swap: iVar1=10, iVar2=20 Before SWAP: iVar1=10, iVar2=20 After SWAP: iVar1=20, iVar2=10调用函数宏替换 int temp = iVar1; iVar1 = iVar2; iVar2 = tem
10、p;【例11.3】宏替换引起的优先级问题1 #define SQUARE(x) x*x 2 #define SQUARE_M(x) (x)*(x) 3 void main() 4 5int iVar=5; 6printf(“SQUARE(%d+3)=%dn“, iVar, SQUARE(iVar+3); 7printf(“SQUARE_M(%d+3)=%dn“, iVar, SQUARE_M(iVar+3); 8 程序运行结果如下: SQUARE(5+3)=23 SQUARE_M(5+3)=64宏替换 iVar+3*iVar+3 =5+3*5+3 =5+15+3=23宏替换 (iVar+3)*
11、(iVar+3 ) =(5+3)*(5+3) =643 预定义宏 n在C语言中预定义了一些有用的宏。这些宏主要是提供当 前编译的信息。宏_LINE_和_STDC_是整型常量,宏 _FILE_ ,_DATE_, _TIME_是字符串量。预定义宏描述 _LINE_当前源代码中的行号,以10进制整数标注_FILE_被编译 的文件的名字,以字符串常量标注_DATE_编译 的日期,以“mm dd yyyy“格式的字符串 标注,如“Nov 15 2007”_TIME_编译 的时间 ,以“hh:mm:ss“格式的字符串标 注 _STDC_如果编译 器接受ANSI C标准,那么值为 1【例11.4】预定义宏1
12、 void main() 2 3printf(“The File is: %sn“,_FILE_); 4printf(“It is compiled on %s at %sn“, _DATE_, _TIME_); 5printf(“The line number of this line is: %dn“,_LINE_); 6 运行结果如下: The File is: SOURCE11_4.C It is compiled on Nov 15 2007 at 16:57:06 The line number of this line is: 54 #include包含n作用:包含文件预处理器发
13、现#include命令后,就会寻找后跟的文件名并 把这个文件的内容包含到当前文件中。n为什么要包含文件呢?包含的文件中有编译器所需的信息。例如stdio.h文件通常包含EOF、NULL、getchar函数和 putchar函数的定义。包含大型头文件并不一定显著增加 程序的大小 。很多情况下,头文件中的内容是编译器产生最终代码所 需的信息,而不是加到最终代码里的具体语句。 功能:功能:文件包含是将指定的某个源文件的内容全部文件包含是将指定的某个源文件的内容全部 包含到当前文件中。用包含到当前文件中。用includeinclude命令实现。命令实现。4 #include包含#include#inc
14、lude的一般形式的一般形式: #include “#include “headfileheadfile“ “ #include #include #include 预处理标记预处理标记“” 先在当前目录 搜索,再搜索标准 目录-可指定路径直接按标准目录 搜索预处理标记会被预处理器进行替换,替换 的结果必须符合前两种形式中的某一种。#include “file2.c”file1.cfile2.cfile1.cfile2.cABA5 条件编译n n功能:功能:希望对程序中的一部分内容在满足一定条 件时编译,否则不编译,或编译另一部分内容。n n命令:命令:#if、#elif、#else、#end
15、ifn n基本格式:基本格式: 说明:说明: #if 常量表达式1 语句. #elif 常量表达式2 语句. #elif 常量表达式3 语句. #else 语句. #endif1.#if和#else分别相当于C语 句中的if、else,它们根据常 量表达式的值来判别是否编 译后面的语句。 2.#elif相当于C中的else if。 3.#else之后不带常量表达式 。 【例11.5】条件编译1 #include 2 #define MY_VERSION 1 3 void main() 4 5 #if MY_VERSION=1 6printf(“This is Version 1.n“); 7 #elif MY_VERSION=2 8printf(“This is Version 2.n“); 9 #elif MY_VERSION=3 10printf(“This is Version 3.n“); 11#else 12printf(“The Version not 1,2,3.n“); 13#endif 14printf(“This line is excuted no matter how the version it is.n“); 15