1、大连大学DaLian University第四章第四章 函函 数数第四章 函 数第1页大连大学DaLian University第四章第四章 函函 数数本章主要内容函数概述函数概述应用函数编程(函数之间数据传递)应用函数编程(函数之间数据传递)值传递值传递地址传递地址传递变量作用域与变量存放类型变量作用域与变量存放类型auto变量、变量、static 变量变量局部变量、全局变量局部变量、全局变量第2页大连大学DaLian University第四章第四章 函函 数数C程序是由函数组成(能够多个)程序是由函数组成(能够多个)有且只有一个有且只有一个main()其它函数其它函数 库函数库函数自定义
2、函数自定义函数函数是结构化程序设计基本模块。函数是结构化程序设计基本模块。含有某种功效代码段含有某种功效代码段通用性强,能够被重复使用。通用性强,能够被重复使用。易于维护,能够独立设计,单独调试。易于维护,能够独立设计,单独调试。划分函数时,考虑功效单一完整。划分函数时,考虑功效单一完整。4.1 函数概述函数概述第3页大连大学DaLian University第四章第四章 函函 数数结构化程序设计思想结构化程序设计思想复杂问题复杂问题main()abca1a2b1b2c1c2结构化程序设计结构化程序设计:也称为,自顶向下、逐步细化。也称为,自顶向下、逐步细化。将复杂系统划分为功效相对独立子系统
3、组合,将复杂系统划分为功效相对独立子系统组合,对各子系统再进行如此划分对各子系统再进行如此划分每个模块,每个模块,在在C语言中表现为函数。语言中表现为函数。第4页大连大学DaLian University第四章第四章 函函 数数C中函数分类:中函数分类:用户角度分:系统函数和用户函数;用户角度分:系统函数和用户函数;参数角度分:有参函数和无参函数;参数角度分:有参函数和无参函数;返回值角度分:有返回值函数和无返回返回值角度分:有返回值函数和无返回值函数。值函数。标准库函数调用标准库函数调用 Turbo CTurbo C中提供了中提供了300300多条标准库函数,多条标准库函数,都放在函数库(都
4、放在函数库(.lib.lib)中,函数说明按功效)中,函数说明按功效分类放在标题文件(分类放在标题文件(.h.h,也称头文件)中。,也称头文件)中。添加一行:添加一行:#include“#include“头文件名称头文件名称”或者或者#include#include 第5页大连大学DaLian University第四章第四章 函函 数数函数例子:函数例子:#include void PrintStar()printf(*n);void main()PrintStar();printf(Hello Everybody!n);PrintStar();使用函数组装程序好处:代码重用 程序模块化 维
5、护方便第6页大连大学DaLian University第四章第四章 函函 数数4.2 4.2 函数定义与调用函数定义与调用 4.2.1 4.2.1 函数定义函数定义#includevoidmain(void)inta,b,c;scanf(“%d,%d”,&a,&b);c=max(a,b);printf(“%d”c);intmax(intx,inty)intz;z=x=y?x:y;return(z);主函数主函数函数体函数体函数类型,返回值类型。函数类型,返回值类型。函数名函数名形式参数说明表。形式参数说明表。定义!定义!调用!调用!函数头函数头第7页大连大学DaLian University第
6、四章第四章 函函 数数函数定义函数定义格式:格式:返回值类型返回值类型 函数名函数名(形式参数列表形式参数列表)申明部分申明部分 功效语句功效语句 返回语句返回语句 /*函数头函数头*/*函数体函数体*/(1)函数头)函数头 返回值类型返回值类型 函数名函数名 形参列表:形参列表:0个或多个,逗号分隔,给出参数名称及类型。个或多个,逗号分隔,给出参数名称及类型。(2)函数体)函数体 代码段,实现功效。一对代码段,实现功效。一对 括起来。括起来。返回语句返回语句return:有返回值:有返回值:return(表示式表示式);或;或return 表示式;返回表示式;返回无返回值:可无无返回值:可无
7、return语句,末尾右语句,末尾右“”作为函数返回。作为函数返回。第8页大连大学DaLian University第四章第四章 函函 数数4.2.24.2.2函数调用函数调用1 1、函数调用形式:、函数调用形式:函数名函数名(实参列表实参列表);v单独语句形式:单独语句形式:max(a,b);printf(“fdsa”);v表示式形式:表示式形式:c=max(a,b);v作为函数参数:作为函数参数:printf(“%d”,max(a,b);1 1、函数调用形式:、函数调用形式:函数名函数名(实参列表实参列表);2 2、函数返回值:被调函数执行后返给主调函数值。、函数返回值:被调函数执行后返给
8、主调函数值。vreturn(表示式);或(表示式);或return表示式;表示式;v可有多条可有多条return语句,碰到一条语句,碰到一条return时,程序即返回。时,程序即返回。v函数没有返回值,能够没有函数没有返回值,能够没有return语句,利用语句,利用“”返回。返回。3 3、函数申明:、函数申明:调用之前,对被调函数要进行申明。如:调用之前,对被调函数要进行申明。如:intmax(intx,inty);第9页大连大学DaLian University第四章第四章 函函 数数#include long Multiply(int,int);void main()int num1,nu
9、m2;long result;scanf(“%d%d”,&num1,&num2);printf(%ldn,Multiply(num1,num2);result=2*Multiply(2*num1,2*num2);printf(%ldn,result);long Multiply(int x,int y)long z;z=x*y;return z;【例4-2】第10页大连大学DaLian University第四章第四章 函函 数数4.3 函数间数据传递函数在调用时,主调函数和被调函数之间普通存在着数据传递。传递有两种方式:值传递和地址传递将值或地址传递给被调函数;将被调函数结果返回给调用函数。
10、主调函数被调函数向被调函数传递数据(值或地址)。将结果返回给主调用函数。第11页大连大学DaLian University第四章第四章 函函 数数传值调用方式:传值调用方式:形参是普通变量形参是普通变量-值参值参(1)形参是普通变量:必须传同类型数值 形参及被调函数内变量只有在被调用时才分配内存单元,此时将实参值初始化给对应形参。形参加实参完全脱离了关系,形参值不影响实参。调用结束时,形参所占据内存单元被释放。(2)实参必须有确定值,方便把这些值传递给形参。(3)实参加形参在数量、位序和类型上必须一致。【例例4-5】观察程序运行结果。观察程序运行结果。#includevoidswap(int,
11、int);voidmain(void)inta,b;a=10;b=20;printf(“调用前:调用前:na=%d,b=%dn”,a,b);swap(a,b);printf(“调用后:调用后:na=%d,b=%dn”,a,b);voidswap(intx,inty)intz;z=x;x=y;y=z;第12页大连大学DaLian University第四章第四章 函函 数数指针变量作形参,必须传同类型地址指针变量作形参,必须传同类型地址(指针)数据。(指针)数据。此时在主调函数和被调函数之间能够实此时在主调函数和被调函数之间能够实现信息现信息“双向传递双向传递”。4.3.2 4.3.2 4.3.
12、2 4.3.2 传地址调用方式传地址调用方式传地址调用方式传地址调用方式例例4-6/*函数参数为指针变量函数参数为指针变量*/voidswap(int*x,int*y);voidmain()inta,b;a=10;b=20;printf(“调用前:调用前:na=%d,b=%dn”,a,b);swap(&a,&b);printf(“调用后:调用后:na=%d,b=%dn”,a,b);voidswap(int*x,int*y)intz;z=*x;*x=*y;*y=z;第13页大连大学DaLian University第四章第四章 函函 数数2.2.2.2.形参为数组类型,实参为数组名形参为数组类型
13、,实参为数组名形参为数组类型,实参为数组名形参为数组类型,实参为数组名#include#includevoidfun(intb);voidfun(intb);main()main()inta10,i;inta10,i;for(i=0;i10;i+)scanf(“%d”,&ai);for(i=0;i10;i+)scanf(“%d”,&ai);fun(a);fun(a);for(i=0;i10;i+)printf(“%d”,ai);for(i=0;i10;i+)printf(“%d”,ai);voidfun(intb)voidfun(intb)intmax,k,i;intmax,k,i;max=b
14、0;max=b0;k=0;k=0;for(i=1;i10;i+)for(i=1;imax)max=bi;k=i;if(bimax)max=bi;k=i;max=b0;b0=bk;bk=max;max=b0;b0=bk;bk=max;例例例例:编写函数,将数组中最大值与第一个数交换。要求在编写函数,将数组中最大值与第一个数交换。要求在编写函数,将数组中最大值与第一个数交换。要求在编写函数,将数组中最大值与第一个数交换。要求在mainmainmainmain()()()()中进行数据输入输出,中进行数据输入输出,中进行数据输入输出,中进行数据输入输出,第14页大连大学DaLian Universi
15、ty第四章第四章 函函 数数【例例4-7】输入输入5个数到数组中,求这个数到数组中,求这5个数平均值。个数平均值。求平均值编写函数实现,并将该值作为返回值。求平均值编写函数实现,并将该值作为返回值。#include#defineN5floataver(intdata,int);voidmain(void)inti,arrayN,av;for(i=0;iN;i+)scanf(%d,&arrayi);av=aver(array,N);printf(av=%fn,av);floataver(intdata,intn)inti;floatavg=0;for(i=0;in;i+)avg+=datai;a
16、vg/=n;return(avg);第15页大连大学DaLian University第四章第四章 函函 数数【例例4-8】输入输入10个数到数组中,再输入一个数到数组中,再输入一实数,判断该数在数组中是否存在?假如实数,判断该数在数组中是否存在?假如存在,输出该数在数组中下标;假如不存存在,输出该数在数组中下标;假如不存在,输出在,输出-1。查找编写函数实现。查找编写函数实现。#includeintsearch(floata,floatx);voidmain()inti,position;floata10,x;printf(输入输入10个实数:个实数:n);for(i=0;i10;i+)sc
17、anf(%f,&ai);printf(输入要找实数:输入要找实数:n);scanf(%f,&x);position=search(a,x);if(position=-1)printf(“没找到。没找到。n);elseprintf(“找到了。下标是找到了。下标是%d,position);intsearch(floata,floatx)intxpos=-1,i;for(i=0;i10;i+)if(ai=x)xpos=i;returnxpos;第16页大连大学DaLian University第四章第四章 函函 数数4.4 函数嵌套调用和递归调用函数嵌套调用和递归调用 C中不允许作嵌套函数定义,各函
18、数之中不允许作嵌套函数定义,各函数之间都是平等和独立。间都是平等和独立。C允许在一个函数定义中出现对另一个函允许在一个函数定义中出现对另一个函数调用。数调用。【例例4-9】函数嵌套调用例子。函数嵌套调用例子。#includefloatfun2(floatx);floatfun1(floatx);voidmain()floata;scanf(%f,&a);printf(%f,myfun1(a);floatfun1(floatx)return2*fun2(x);floatfun2(floatx)returnx0?x:-x;第17页大连大学DaLian University第四章第四章 函函 数数【
19、例例4-10】使用函数嵌套调用编程,计算使用函数嵌套调用编程,计算S。voidmain()intN,K;scanf(%d%d,&N,&K);printf(n%.0fn,fsum(N,K);分析分析(1)求累加和编一函数)求累加和编一函数fsum();(2)累加每一项,再编一函数)累加每一项,再编一函数fexp()(3)循环中,进行累加时,调用)循环中,进行累加时,调用fexp()求出该项求出该项double fsum(int n,int k)double sum=0;int i;for(i=0;in;i+)sum+=fexp(i,k);return sum;double fexp(int n,
20、int k)double power=1;int i;for(i=0;ik;i+)power*=n;return power;第18页大连大学DaLian University第四章第四章 函函 数数4.4.2 4.4.2 函数递归调用函数递归调用含义:一个函数在它函数体内直接或间接含义:一个函数在它函数体内直接或间接地调用它本身称为递归调用。地调用它本身称为递归调用。用递归法处理问题,应该符合以下用递归法处理问题,应该符合以下2个条个条件:件:边界问题(也称基本问题)有直接解。边界问题(也称基本问题)有直接解。原问题能够转化成一个规模较小新问题,新原问题能够转化成一个规模较小新问题,新问题求
21、解方法与原问题相同。问题求解方法与原问题相同。第19页大连大学DaLian University第四章第四章 函函 数数【例例4-11】计算计算n!。使用递归函数实现。使用递归函数实现。long fac(int n)if(n=1)return(1);else return n*fun(n-1);void main()int n;scanf(“%d”,&n);printf(“%d”,fac(n);第20页大连大学DaLian University第四章第四章 函函 数数【例例5-】汉诺塔问题汉诺塔问题(Hanoi)(Hanoi)问题提出:问题提出:相传相传是是在古印度圣庙在古印度圣庙中一个游戏。
22、中一个游戏。在一块铜板装置上,有三根杆在一块铜板装置上,有三根杆A A、B B、C C,在,在A A杆自下杆自下而上、由大到而上、由大到。小放置小放置6464个金盘。个金盘。游戏目标游戏目标:把把A A杆上金盘全部移到杆上金盘全部移到C C杆上,并仍保持原杆上,并仍保持原有次序叠好。有次序叠好。操作规则:操作规则:每次只能移动一个盘子每次只能移动一个盘子;移动过程中三根移动过程中三根杆上一直保持大盘在下,小盘在上,操作过程中盘子杆上一直保持大盘在下,小盘在上,操作过程中盘子能够置于能够置于A A、B B、C C任一杆上。任一杆上。第21页大连大学DaLian University第四章第四章
23、函函 数数4.5变量作用域与存放类型变量作用域与存放类型C程序中变量使用规则是:先定义后使用。定义形式中:类型:表明变量占用内存空间大小;位置(函数内与外):表明变量在程序中作用域。普通,还要说明其存放类型,说明变量存放方式。不一样存放方式影响变量在内存中存在时间。第22页大连大学DaLian University第四章第四章 函函 数数4.5.1局部变量与全局变量局部变量与全局变量 局部变量:在函数内部或复合语句内部局部变量:在函数内部或复合语句内部定义变量(包含函数定义变量(包含函数形参形参)。)。不一样函数内局部变量之间没相关系,同名不一样函数内局部变量之间没相关系,同名也互不影响。也互
24、不影响。局部变量同名时,当前局部变量有效。局部变量同名时,当前局部变量有效。第23页大连大学DaLian University第四章第四章 函函 数数【例例4-12】函数局部变量应用举例。函数局部变量应用举例。void func1(int a,int b)int x;printf(“func1 x:%x”,&x);void func2()int x;printf(“func2 x:%x”,&x);voidmain()intx,y;func1(3,4);func2();printf(“mainxDS:%x”,&x);第24页大连大学DaLian University第四章第四章 函函 数数【例例
25、4-13】复合语句中局部变量举例。复合语句中局部变量举例。void main()int i,j;i=2;j=3;int i;i=5;printf(Inter i=%d,j=%dn,i,j);printf(Outer i=%d,j=%dn,i,j);第25页大连大学DaLian University第四章第四章 函函 数数2.全局变量全局变量在函数体外部定义变量称为全局变量。在函数体外部定义变量称为全局变量。局部变量属于所在函数,而全局变量属于全部局部变量属于所在函数,而全局变量属于全部函数,能够被当前文件其它函数使用。函数,能够被当前文件其它函数使用。全局变量和局部变量同名时,全局变量和局部变
26、量同名时,当前局部变量有效,全局变量被屏蔽。当前局部变量有效,全局变量被屏蔽。普通来说,在较大程序中要防止出现全局变量普通来说,在较大程序中要防止出现全局变量和局部变量同名情况。和局部变量同名情况。第26页大连大学DaLian University第四章第四章 函函 数数【例例4-14】全局变量应用举例。全局变量应用举例。int qNum=10;void main()printf(%dn,qNum);func1();printf(%dn,qNum);func2();printf(%dn,qNum);void func1()qNum=1;void func2()qNum=2;第27页大连大学Da
27、Lian University第四章第四章 函函 数数全局变量说明:全局变量说明:extern 数据类型数据类型 全局变量名;全局变量名;#include void func1()extern int sum;/申明申明 sum=1;int sum=0;void main()func1();printf(%dn,sum);第28页大连大学DaLian University第四章第四章 函函 数数全局变量优缺点:全局变量优缺点:使用全局变量优点使用全局变量优点 降低实参和形参数据传递带来时间消耗。降低实参和形参数据传递带来时间消耗。使用全局变量缺点:使用全局变量缺点:全局变量保留在静态存贮区,编
28、译时为其分配全局变量保留在静态存贮区,编译时为其分配空间,整个程序结束才释放该空间。所以全局空间,整个程序结束才释放该空间。所以全局变量生存期比较长,变量生存期比较长,过多全局变量占用较多内过多全局变量占用较多内存单元。存单元。全局变量破坏了函数封装性能。全局变量破坏了函数封装性能。全局变量使函数代码可读性降低。全局变量使函数代码可读性降低。第29页大连大学DaLian University第四章第四章 函函 数数4.5.2变量存放类型变量存放类型 动态存贮区和静态存贮区动态存贮区和静态存贮区 程序运行后,内存中可供程序使用存贮空间程序运行后,内存中可供程序使用存贮空间分为三个部分。分为三个部
29、分。代码区存放:代码区存放:程序二进制代码。程序二进制代码。静态存贮区和动态存贮区:静态存贮区和动态存贮区:存放程序相关数存放程序相关数据。据。静态存贮区里:全局变量、静态变量。静态存贮区里:全局变量、静态变量。动态存贮区里:函数内定义变量、形参。动态存贮区里:函数内定义变量、形参。特点:特点:调用时,为变量动态分配内存空间;调用时,为变量动态分配内存空间;调用结束,释放该变量内存空间。调用结束,释放该变量内存空间。变量存贮类别有三种:变量存贮类别有三种:auto、static、register。第30页大连大学DaLian University第四章第四章 函函 数数 auto auto存放
30、类型(关键字能够省略)存放类型(关键字能够省略)在默认情况下,全部局部变量(包含形参)都是在默认情况下,全部局部变量(包含形参)都是autoauto变量变量#includevoidmain(void)autointa,b;scanf(“%d,%d”,&a,&b);if(ba)intt;t=a;a=b;b=t;printf(“Max=%d”,a);ab作作用用域域t作作用用域。域。生存期:生存期:变量都拥有自己内存空间。变量都拥有自己内存空间。从申请从申请-被释放被释放,这段时间称为变量这段时间称为变量生存期生存期。register存放类型存放类型其其作用域、生存期与作用域、生存期与auto相同
31、,相同,差异在于,假如差异在于,假如CPU内部存放内部存放器空闲,器空闲,则使用存放器作为变量则使用存放器作为变量存放单元,以提升速度。存放单元,以提升速度。主要是循环变量,整形和字符型。主要是循环变量,整形和字符型。第31页大连大学DaLian University第四章第四章 函函 数数static(静态静态)存放类型存放类型作用域:作用域:函数内定义局部静态变量,在该函数之外不可见。函数内定义局部静态变量,在该函数之外不可见。生存期生存期:从编译从编译-整个程序结束。整个程序结束。位于静态存贮区,在函数调用结束后,值依然存在,位于静态存贮区,在函数调用结束后,值依然存在,并影响到下一次调
32、用过程。并影响到下一次调用过程。voidrow();voidmain()inti;for(i=1;i=9;i+)row();voidrow()static inta=1;inti;for(i=1;i=9;i+)printf(“%5d”,a*i);printf(“n”);a+;a作用域作用域生存期从编译开始到程序结束。生存期从编译开始到程序结束。第32页大连大学DaLian University第四章第四章 函函 数数【例例4-15】static局部变量应用举例。局部变量应用举例。#includeintf(intx)inta=10;staticintstc=1;stc=stc+x+a;retur
33、nstc;voidmain()printf(%dn,f(1);printf(%dn,f(1);第33页大连大学DaLian University第四章第四章 函函 数数关于关于static局部变量提出几点注意:局部变量提出几点注意:存放在静态区,生存期比较长,从编译开始它就存在,存放在静态区,生存期比较长,从编译开始它就存在,整个程序结束后才被释放。整个程序结束后才被释放。从作用域来看,它是一个局部变量,属于当前函数;从作用域来看,它是一个局部变量,属于当前函数;即,当前函数内可见,其它函数即,当前函数内可见,其它函数 不可见。不可见。对初值处理不一样。对初值处理不一样。auto变量定义时假如
34、没有初始化,那么它是一个随机值;变量定义时假如没有初始化,那么它是一个随机值;static局部变量假如没有初始化,编译器自动将其初始化为局部变量假如没有初始化,编译器自动将其初始化为 值值 0 或或 空字符。空字符。在程序中尽可能不用或少用在程序中尽可能不用或少用static局部变量。原因主要有:局部变量。原因主要有:static局部变量生存期长,比较浪费内存;局部变量生存期长,比较浪费内存;使用使用static局部变量会造成函数屡次调用之间发生联络,使代码可读局部变量会造成函数屡次调用之间发生联络,使代码可读性降低。性降低。第34页大连大学DaLian University第四章第四章 函函
35、 数数4.static 型全局变量型全局变量 C程序能够由多个源文件组成。程序能够由多个源文件组成。一个文件中定义全局变量,其它文件中能一个文件中定义全局变量,其它文件中能够使用(够使用(用用extern方式申明后)方式申明后)。假如限制本文件中全局变量不能被其它文假如限制本文件中全局变量不能被其它文件使用,能够在件使用,能够在全局变量定义前加关键字全局变量定义前加关键字static。static型全局变量作用域:本文件内。型全局变量作用域:本文件内。第35页大连大学DaLian University第四章第四章 函函 数数 【举例举例】static全局变量应用。全局变量应用。/文件文件f1.
36、c里代码以下:里代码以下:#include#includestaticintgs=0;voidfunc(intx);voidmain()func(3);printf(%d,gs);/文件文件f2.c里代码以里代码以下:下:externintgs;voidfunc(intx)gs+=x;第36页大连大学DaLian University第四章第四章 函函 数数4.6 外部函数和内部函数外部函数和内部函数 当一个程序由多个源文件组成时,当一个程序由多个源文件组成时,能够指定一个文件中函数能被能够指定一个文件中函数能被其它文件调用;其它文件调用;也能够指定该函数只能被也能够指定该函数只能被本文件使用
37、本文件使用;从这个意义上,函数能够分为外部函数和内部从这个意义上,函数能够分为外部函数和内部函数。函数。第37页大连大学DaLian University第四章第四章 函函 数数4.6.1 外外 部部 函函 数数 一个函数假如能够被其它源文件调用,称为外部函数。一个函数假如能够被其它源文件调用,称为外部函数。定义外部函数时,在函数头最左面加关键字定义外部函数时,在函数头最左面加关键字externextern,表明该函数是一个外部函数表明该函数是一个外部函数 省略省略externextern关键字,则系统默认为外部函数关键字,则系统默认为外部函数 externintmax(inta,intb)r
38、eturnab?a:b;文件文件f1.c里代码以下:里代码以下:externvoidprintstar();/*extern能够省略不写能够省略不写*/voidmain()printstar();文件文件f2.c里代码以下:里代码以下:voidprintstar()printf(*n);这里这里f1.cmain函数调用了函数调用了f2.c外部函数外部函数printstar。第38页大连大学DaLian University第四章第四章 函函 数数4.6.2 内部函数内部函数假如一个函数只能被假如一个函数只能被本文件中函数调用本文件中函数调用,该函,该函数就称为内部函数,数就称为内部函数,定义内
39、部函数时,在函数最左面加关键字定义内部函数时,在函数最左面加关键字static staticintmax(inta,intb)returnab?a:b;第39页大连大学DaLian University第四章第四章 函函 数数文件文件f1.c 里代码:里代码:void func();static void printstar()printf(printstar in f1.c.n);void main()printstar();func();文件文件f2.c里代码:里代码:staticvoidprintstar()printf(printstarinf2.c.n);voidfunc()prin
40、tstar();第40页大连大学DaLian University第四章第四章 函函 数数4.7.2 在在VC+下多文件程序运行下多文件程序运行在在VC+环境下,编译和运行由多个源文件环境下,编译和运行由多个源文件组成程序操作以下:组成程序操作以下:方法一,新建一个工程,向其中添加已方法一,新建一个工程,向其中添加已经有源文件。经有源文件。方法二,新建一个工程,在其中创建多方法二,新建一个工程,在其中创建多个源文件个源文件。第41页大连大学DaLian University第四章第四章 函函 数数补充 编译预处理C语言还有一类语言还有一类编译预处理语句编译预处理语句。作用是作用是在编译时对程序
41、作一定处理在编译时对程序作一定处理,满足特定处理要求。,满足特定处理要求。编译预处理语句语法形式:编译预处理语句语法形式:#关键词关键词参数表参数表宏定义预处理宏定义预处理1.1不带参数宏定义不带参数宏定义作用:作用:定义常量名,提升程序可读性,便于修改。定义常量名,提升程序可读性,便于修改。格式:格式:#define宏名宏名字符串字符串#definePI3.1415926voidmain(void)floatr;scanf(“%f”,&r)printf(“%fn”,PI*r*r);编译时用字符串替换宏名。编译时用字符串替换宏名。3.1415926第42页大连大学DaLian Universi
42、ty第四章第四章 函函 数数说明:宏名普通用大写;宏名普通用大写;编译时用字符串无条件替换宏名;编译时用字符串无条件替换宏名;#definePI3.1415926;PI*r*r3.1415926*r*r;宏名有效范围,从定义到程序尾。也能够经过宏名有效范围,从定义到程序尾。也能够经过#undef修改修改定义范围。定义范围。#defineG9.8voidmain(void)#undefGG范围范围能够在宏定义字符串中使用已定义宏名。能够在宏定义字符串中使用已定义宏名。”字符串中宏名不替换。字符串中宏名不替换。#defineR3.0#definePI3.14159#defineSPI*R*Rpri
43、ntf(“S=%f”,S);不替换。不替换。第43页大连大学DaLian University第四章第四章 函函 数数1.2 带参数宏定义格式:格式:#define宏名宏名(参数表参数表)含参数字符串含参数字符串#defineS(a,b)a*barea=S(4,3);替换过程:替换过程:将实际参数替换宏定义参数。将实际参数替换宏定义参数。替换字符串中参数。替换字符串中参数。替换整个宏。替换整个宏。4*3带参宏与函数区分:带参宏与函数区分:带参宏不分配内存单元,不返回值,只是在编译时按规则替换。带参宏不分配内存单元,不返回值,只是在编译时按规则替换。关于带参宏说明:关于带参宏说明:要严格按格式书
44、写,不然会造成错误。要严格按格式书写,不然会造成错误。#defineS(a,b)a*bS(3,4)被替换成:被替换成:(a,b)a*b(3,4)参数有可能用到表示式时,参数字符要加()。参数有可能用到表示式时,参数字符要加()。#defineS(r)PI*r*rS(a+b)替换为:替换为:PI*a+b*a+b#defineS(r)PI*(r)*(r)S(a+b)替换为:替换为:PI*(a+b)*(a+b)第44页大连大学DaLian University第四章第四章 函函 数数 文件包含格式:格式:#include#include”被包含文件名被包含文件名”表示编译系统定义路径;表示编译系统定
45、义路径;“”表示用户指明路径。表示用户指明路径。作用:作用:将指定文件内容和当前文件一起编译。将指定文件内容和当前文件一起编译。说明:说明:(1)一个)一个#include只能包含一个文件。只能包含一个文件。(2)普通将宏定义及函数原型申明放在包含文件中。)普通将宏定义及函数原型申明放在包含文件中。(3)被包含文件普通扩展名为)被包含文件普通扩展名为.h,称为头文件。,称为头文件。第45页大连大学DaLian University第四章第四章 函函 数数 条件编译C可经过条件控制,让编译系统编译不一样程序段。可经过条件控制,让编译系统编译不一样程序段。条件编译有三种形式:条件编译有三种形式:#
46、ifdef标识符标识符programseg1#elseprogramseg2#endif#ifndef标识符标识符programseg1#elseprogramseg2#endif12条件?条件?满足满足编译程序段编译程序段1不满足不满足编译程序段编译程序段2第46页大连大学DaLian University第四章第四章 函函 数数举例:经过条件编译选择求最大值或最小值#includevoidmain(void)inta,b;scanf(“%d,%d”,&a,&b);#ifdefMAXprintf(“%d”,a=b?a:b);#elseprintf(“%d”,a=b?a:b);#endif#defineMAX#includevoidmain(void)inta,b;scanf(“%d,%d”,&a,&b);printf(“%d”,a=b?a:b);第47页