版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、2021-4-221 第第 6 章章 函数与宏定义函数与宏定义 6.1 函数概念函数概念 6.2 函数定义的一般形式函数定义的一般形式 6.3 函数参数和函数的值函数参数和函数的值 6.4 函数的调用函数的调用 6.5 函数的嵌套调用函数的嵌套调用 6.6 函数的递归调用函数的递归调用 2021-4-222 6.7 局部变量和全局变量局部变量和全局变量 6.8 动态存储变量与静态存储变量动态存储变量与静态存储变量 6.9 内部函数和外部函数内部函数和外部函数 6.10 编译预处理编译预处理 6.11 “文件包含文件包含” 处理处理 6.12 条件编译条件编译 2021-4-223 6.1 函数
2、概念函数概念 在进行程序设计时,程序员总是将复杂的问题进行在进行程序设计时,程序员总是将复杂的问题进行 分解分解, 化整为零。编写一段小程序就能解决一个小问题,化整为零。编写一段小程序就能解决一个小问题, 然后将这些小程序拼装起来就能解决非常大而复杂的问然后将这些小程序拼装起来就能解决非常大而复杂的问 题。在题。在 C 中,这些小程序统称为函数。中,这些小程序统称为函数。 在在 C 中,由系统提供的函数放在函数库中供用户选中,由系统提供的函数放在函数库中供用户选 用,以减少重复编写程序模块的工作量。用,以减少重复编写程序模块的工作量。 所有函数都是平行的,相互独立不能嵌套,但可以相所有函数都是
3、平行的,相互独立不能嵌套,但可以相 互调用互调用(main函数不能被其它函数调用函数不能被其它函数调用)。 C 函数分标准函数函数分标准函数(库函数库函数)和自定义函数。和自定义函数。 C 函数本身分有参函数和无参函数。函数本身分有参函数和无参函数。 2021-4-224 6.2 函数定义的一般形式 1无参函数的定义形式无参函数的定义形式 类型标识符类型标识符 函数名函数名( ) 说明部分说明部分 ; 语句;语句; 无参函数一般不需要返回函数值,可以省略类型标识符。无参函数一般不需要返回函数值,可以省略类型标识符。 2有参函数的定义形式有参函数的定义形式 类型标识符类型标识符 函数名函数名(形
4、式参数表形式参数表) 形式参数说明;形式参数说明; 说明部分说明部分 ; 语句;语句; 无分号无分号! 无分号无分号! 2021-4-225 3“ 空函数空函数 ” 例:例: int max(x,y) int x, y;/ 形式参数说明形式参数说明 / int z;/ 函数体中的说明部分函数体中的说明部分 / z=xy ? x : y; return(z); 类型说明符类型说明符 函数名函数名( ) “空函数空函数”什么操作也不做。其作用是在此处留一函什么操作也不做。其作用是在此处留一函 数的位置,以便将来扩充功能之用。函数名也在将来数的位置,以便将来扩充功能之用。函数名也在将来 换取实际的函
5、数名。换取实际的函数名。 这两行可以写成一行:这两行可以写成一行: int max(int x, int y) 2021-4-226 6.3 函数参数和函数的值函数参数和函数的值 1形式参数和实际参数形式参数和实际参数 例例6.1 从键盘输入两个数,输出其中较大的一个。从键盘输入两个数,输出其中较大的一个。 main( ) int a, b, c ; scanf(“%d,%d”, c=max(a,b); / a, b为实际参数为实际参数 / printf(“Max is %d”,c); max(int x,int y) / x, y为形式参数为形式参数 / int z; z=xy ? x :
6、y; return(z); 2021-4-227 形参变量在被调用前不占用存储单元;在被调用结束形参变量在被调用前不占用存储单元;在被调用结束 后,形参所占存储单元亦被释放。后,形参所占存储单元亦被释放。 实参可以是常量、变量或表达式。实参可以是常量、变量或表达式。 必须指定形参类型,且必须与实参的类型一致。必须指定形参类型,且必须与实参的类型一致。 实参对形参的数据传递是实参对形参的数据传递是“值传递值传递”。即单向传递,。即单向传递, 不能逆传。不能逆传。 可以在形参表中直接说明形参类型。如:可以在形参表中直接说明形参类型。如: int max(int x, int y); float f
7、un(int a10, int n); 注意注意: 2021-4-228 函数的返回值是通过函数的返回值是通过return语句获得的。当不需返回语句获得的。当不需返回 函数值时,可省去函数值时,可省去return语句。语句。 return语句的后面可以有括号,也可以没有。如:语句的后面可以有括号,也可以没有。如: return z ; return(z); return语句的后面可以是变量,也可以是表达式。如:语句的后面可以是变量,也可以是表达式。如: return(x y ? x : y); return语句返回值的类型应与该函数的返回值类型一语句返回值的类型应与该函数的返回值类型一 致。否
8、则以函数返回值致。否则以函数返回值 类型为准。类型为准。 2函数的返回值函数的返回值 2021-4-229 若函数中没有若函数中没有return语句,则该函数被调用后也会带语句,则该函数被调用后也会带 回回不确定的值不确定的值。如:。如:main( ) int a, b, c ; a=printstar( ); b=print_message( ); c=printstar( ); printf(“%d,%d,%dn”,a,b,c); 输出的输出的a, b, c的值将是随机值。的值将是随机值。 为了明确表示不需要函数返回值,可以用为了明确表示不需要函数返回值,可以用“void”定定 义函数为义
9、函数为“无类型无类型”。此时,不得使用。此时,不得使用a=printstar( )之之 类的语句。类的语句。 凡不需要返回值的函数,一般均定义为凡不需要返回值的函数,一般均定义为“void”类型。类型。 2021-4-2210 1函数调用的一般形式函数调用的一般形式 函数名函数名(实参表实参表); 说明:说明: 对于无参函数,尽管没有对于无参函数,尽管没有“实参表实参表”,但也不得省,但也不得省 略括号。略括号。 “实参表实参表”中的参数之间用中的参数之间用逗号逗号分开。分开。 实参与形参之间的个数及类型必须一一对应。实参与形参之间的个数及类型必须一一对应。 对实参求值的顺序是自左至右还是自右
10、至左对实参求值的顺序是自左至右还是自右至左, 视具体视具体 的系统而定。标准的系统而定。标准C 是按是按自右至左自右至左的顺序求值。的顺序求值。 6.4 函数的调用函数的调用 2021-4-2211 例例6.2 main( ) int i =2 , p ; p = fun( i , + + i ); printf ( “%d”, p ) ; int fun ( a , b ) int a , b ; int c ; if ( a b ) c = 1; else if ( a = = b ) c = 0 ; else c = 1 ; return( c ) ; 输出结果:输出结果: 0 注意注意
11、:这里是按:这里是按自右至左自右至左 求值的,相当于求值的,相当于fun(3,3)。 若按自左至右求值,则相若按自左至右求值,则相 当于当于fun(2,3), 则输出为则输出为-1。 2021-4-2212 调用函数,可以有如下三种方式:调用函数,可以有如下三种方式: 将函数调用作为一个语句。如:将函数调用作为一个语句。如: printf(“MS C pragramming”); gets(s); 将被调用的函数写在表达式中。如:将被调用的函数写在表达式中。如: c=2 max(a, b); 注意注意:被调用函数:被调用函数max必须有确定的返回值。必须有确定的返回值。 将函数调用作为一个函数
12、的实参。如:将函数调用作为一个函数的实参。如: m=max(max(a, b), c); 3对被调用函数的说明对被调用函数的说明 在一个函数中调用另一个函数时:在一个函数中调用另一个函数时: 如果被调函数为库函数,则应在文件开头用如果被调函数为库函数,则应在文件开头用“#include”命令命令 声明相应的声明相应的“头文件头文件”。如:。如: #include “stdio.h” #include “math.h” 2函数调用的方式函数调用的方式 2021-4-2213 类型标识符类型标识符 被调函数名被调函数名( ); 如:如:float add( ); 如果被调函数为自定义函数且其定义在
13、主调函数定义之前,则如果被调函数为自定义函数且其定义在主调函数定义之前,则 在主调函数中可不必在主调函数中可不必声声明其类型。因为编译程序已知道其类型。明其类型。因为编译程序已知道其类型。 如果被调函数的值是整型或字符型,可不必声明类型,系统自如果被调函数的值是整型或字符型,可不必声明类型,系统自 动按整型说明。动按整型说明。 如果在所有被调函数定义之前、在文件的开头、在函数的外部如果在所有被调函数定义之前、在文件的开头、在函数的外部 已对被调函数作了类型说明,则在各主调函数中可不必说明其已对被调函数作了类型说明,则在各主调函数中可不必说明其 类型。如:类型。如: char letter( )
14、; float f( ); int i( ); main( ) / 不必说明它所调用的函数的类型不必说明它所调用的函数的类型 / 如果被调函数为自定义函数且其定义在主调函数定义之后,则如果被调函数为自定义函数且其定义在主调函数定义之后,则 应在主调函数中声明其类型应在主调函数中声明其类型(称之为称之为”函数声明函数声明”)。其语句形式。其语句形式 为:为: 2021-4-2214 例例6.3 编程求编程求11999之间的数之间的数m,而,而m、m2和和m3均是回文数均是回文数(数数 位左右对称位左右对称)。如:如:m=11、m2=121、m3=1331, 。 #include “stdio.h
15、” main( ) long int m; for (m=11; m1000; m+) if (fun(m) int fun(long n) long i, k; i= n; k=0; while (i) k=i%10+k 10; i = i /10; if (k=n) return 1; else return 0; 2021-4-2215 C 语言函数的定义都是相互平行、独立的,语言函数的定义都是相互平行、独立的,不能不能 嵌套定义。但可以嵌套调用函数嵌套定义。但可以嵌套调用函数。所谓函数的嵌套调。所谓函数的嵌套调 用就是在被调用的函数中又调用另外的函数。用就是在被调用的函数中又调用另外的
16、函数。 6.6 函数的递归调用函数的递归调用 在调用一个函数的过程中又出现直接或间接地调在调用一个函数的过程中又出现直接或间接地调 用该函数本身,称为函数的递归调用。用该函数本身,称为函数的递归调用。 6.5 函数的嵌套调用函数的嵌套调用 2021-4-2216 例例6.4 有有5人排成一队,从最后一人开始,其年龄均比人排成一队,从最后一人开始,其年龄均比 前面的人大前面的人大2岁,而最前面的人年龄是岁,而最前面的人年龄是10岁,问最后岁,问最后 一人的年龄是多少岁?一人的年龄是多少岁? Main( ) age(5)age(4)+2 age( ) n=5 age(3)+2 age( ) n=4
17、 age(2)+2 age( ) n=3 age(1)+2 age( ) n=2 age(1) =10 age( ) n=1 age(1)=10age(1)=12age(1)=14age(1)=16age(1)=18输出输出age(5) 2021-4-2217 函数的递归调用利用了堆栈技术。在本例中:函数的递归调用利用了堆栈技术。在本例中: Age(5) Age(51)+2 Age(41)+2 Age(31)+2 Age(21)+210+2=12 12+2=14 14+2=16 16+2=18 18 Age(21)+2Age(31)+2Age(41)+2Age(51)+2 Age(5) Age
18、(5) Age(51)+2 Age(41)+2 Age(31)+2 Age(21)+2 入栈入栈出栈出栈出栈结果出栈结果 2021-4-2218 1局部变量局部变量 在一个函数内部定义的变量,只能在本函数内使用和在一个函数内部定义的变量,只能在本函数内使用和 有效,称为有效,称为“局部变量局部变量”。 主函数主函数main中定义的变量,也只能在主函数内使用中定义的变量,也只能在主函数内使用 和有效。和有效。 不同函数中可以使用相同名字的变量,且互不干扰。不同函数中可以使用相同名字的变量,且互不干扰。 形式参数也是局部变量,也只能在所在函数内使用和形式参数也是局部变量,也只能在所在函数内使用和
19、有效。有效。 可以在一个函数内的复合语句中定义变量,且这些变可以在一个函数内的复合语句中定义变量,且这些变 量只在本复合语句中有效。量只在本复合语句中有效。 这种复合语句也称为这种复合语句也称为“分程序分程序”或或“子模块子模块”。 2全局变量全局变量 在函数在函数(包括包括main函数函数)外定义的变量为外部变量,外定义的变量为外部变量, 称为称为“全局变量全局变量”。全局变量的有效范围为从定义变。全局变量的有效范围为从定义变 量的位置开始到本源文件结束。量的位置开始到本源文件结束。 6.7 局部变量和全局变量局部变量和全局变量 2021-4-2219 如无必要,不要使用全局变量。因为全局变
20、量既降低程序的清如无必要,不要使用全局变量。因为全局变量既降低程序的清 晰性和函数的通用性,且又在程序的全部执行过程中都占用存晰性和函数的通用性,且又在程序的全部执行过程中都占用存 储空间。储空间。 在文件开头定义的外部变量才可在整个文件范围内使用,若在在文件开头定义的外部变量才可在整个文件范围内使用,若在 定义点之前的函数需引用外部变量,则可用关键字定义点之前的函数需引用外部变量,则可用关键字“extern” 作作“外部变量说明外部变量说明”。 注意注意:外部变量定义和外部变量说明并不是同一回事。外部变量:外部变量定义和外部变量说明并不是同一回事。外部变量 的定义只能有一次,它的位置在所有函
21、数之外。而同一程序中的定义只能有一次,它的位置在所有函数之外。而同一程序中 的外部变量说明可以有多次,它的位置在函数之内的外部变量说明可以有多次,它的位置在函数之内(哪个函数哪个函数 要用就在哪个函数中说明要用就在哪个函数中说明)。系统根据外部变量的定义。系统根据外部变量的定义(而不是而不是 根据外部变量的说明根据外部变量的说明)分配存储单元。对外部变量的初始化只分配存储单元。对外部变量的初始化只 能在能在“定义定义”时进行,时进行,“extern”只是申明该变量是一个已在只是申明该变量是一个已在 外部定义过的变量而已外部定义过的变量而已。 如果在同一源文件中,外部变量与局部变量同名,则在局部
22、变如果在同一源文件中,外部变量与局部变量同名,则在局部变 量的作用范围内,外部变量不起作用。量的作用范围内,外部变量不起作用。 全局变量增加了函数间数据联系的渠道。由于同一文件中的所全局变量增加了函数间数据联系的渠道。由于同一文件中的所 有函数都能引用全局变量的值,当需要从一个函数中带回多个值有函数都能引用全局变量的值,当需要从一个函数中带回多个值 时,就能克服函数调用只能返回一个值的局限性。时,就能克服函数调用只能返回一个值的局限性。 2021-4-2220 输出结果:输出结果: 10, 4, 8 10, 2, 5 例例6.5 #include “stdio.h” main( ) int a
23、=1, b=2, c=3; a+; c+=b; int b=4, c; c=2 b; a+=c; printf(“%d,%d,%dn”, a, b, c); printf(“%d,%d,%dn”, a, b, c); C编译內存管理示意图编译內存管理示意图: 程序区 静态存储区 用户定义存储区 动态存储区 数据区 2021-4-2222 1变量的存储类别变量的存储类别 静态变量在程序的运行期间占用固定的存储空间,静态变量在程序的运行期间占用固定的存储空间, 直到程序的终止而释放;而动态变量是在程序的运直到程序的终止而释放;而动态变量是在程序的运 行期间随着函数的调用随时动态地占用和释放存储行期
24、间随着函数的调用随时动态地占用和释放存储 空间。即存储方式是根据变量的存储类别决定的。空间。即存储方式是根据变量的存储类别决定的。 C的存储类别有四种:的存储类别有四种: 自动的自动的(auto)、静态的、静态的(static)、寄存器的、寄存器的(register)、 外部的外部的(extern)。 2局部变量的存储方式局部变量的存储方式 1) 函数中的局部变量若未专门说明,都是由编译系统函数中的局部变量若未专门说明,都是由编译系统 自动动态分配存储空间,这类局部变量称为自动变自动动态分配存储空间,这类局部变量称为自动变 量,其类型说明前不论是否有关键字量,其类型说明前不论是否有关键字“au
25、to”,都属,都属 于动态存储类别。于动态存储类别。 6.8 动态存储变量与静态存储变量动态存储变量与静态存储变量 2021-4-2223 局部静态变量在静态存储区分配存储单元,在程序的整个运行局部静态变量在静态存储区分配存储单元,在程序的整个运行 期间都不释放。而动态变量在动态存储区分配存储单元,函数期间都不释放。而动态变量在动态存储区分配存储单元,函数 调用结束后即释放。调用结束后即释放。 局部静态变量在编译时只赋初值一次,以后每次被调用时不再局部静态变量在编译时只赋初值一次,以后每次被调用时不再 重新赋值而只保留前次被调用结束时的值。动态变量赋初值不重新赋值而只保留前次被调用结束时的值。
26、动态变量赋初值不 是在编译时而是在函数被调用时进行的,函数每次被调用时重是在编译时而是在函数被调用时进行的,函数每次被调用时重 新赋值,相当于赋值语句。新赋值,相当于赋值语句。 静态变量若未赋初值,则在编译时自动赋初值静态变量若未赋初值,则在编译时自动赋初值0 (数值型数值型)或空字或空字 符符(字符型字符型)。而动态变量若未赋初值,则其值是不确定的。而动态变量若未赋初值,则其值是不确定的。 虽然局部静态变量在函数被调用结束后其值仍然存在,但其它虽然局部静态变量在函数被调用结束后其值仍然存在,但其它 函数是不能引用的。函数是不能引用的。 2) 若希望被调函数在结束后,其局部变量占用的存储空若希
27、望被调函数在结束后,其局部变量占用的存储空 间不释放,以便保留其变量的值,用于下次调用该函数,间不释放,以便保留其变量的值,用于下次调用该函数, 则用则用“static”说明为说明为 “局部静态变量局部静态变量”。 2021-4-2224 3全局变量的存储方式全局变量的存储方式 在文件开头用在文件开头用extern作说明,可以引用另一个文件中作说明,可以引用另一个文件中 定义的全局变量。但用定义的全局变量。但用static说明的全局变量不能被说明的全局变量不能被 其它文件引用。其它文件引用。 例例6.6 打印打印1到到5的阶乘值。的阶乘值。 int fac(n) int n; static i
28、nt f =1; / 定义定义f 为为int型静态变量型静态变量 / f = f n ; return( f ); main( ) int i; for (i=1; i(c+d)?(a+b):(c+d) 如果第一行写成:如果第一行写成: #define MAX(x,y) xy ? x : y 则则 这里的这里的 t 展开后为展开后为 t = a+bc+d?a+b:c+d 因为因为置换展开是用置换展开是用“表达式表达式”对等对等的置换的置换“形参表形参表” 中的参数中的参数。 定义带参数的宏,可以实现一些简单的函数功能。定义带参数的宏,可以实现一些简单的函数功能。 如:如: #define MA
29、X(x,y) (x)(y)?(x) : (y) main( ) int a, b, c, t ; t = MAX(a+b, c+d); 2021-4-2233 例例6.9(演示演示) #include “stdio.h” #define N 2 #define M N+1 #define NUM (M+1) M/2 main( ) int i, n=0; for (i=1; i=NUM; i+) n+; printf(“%2d”, n); printf(“n”); 输出结果:输出结果: 1 2 3 4 5 6 7 8 NUM被代换展开后为:被代换展开后为:( 2+1+1) 2+1/2 一个一个
30、include命令只能指定一个被包含文件,命令只能指定一个被包含文件, 如果要包含如果要包含n个文件,则要用个文件,则要用n个个include命令。命令。 2021-4-2234 如果如果“文件文件1”包含包含“文件文件2”,而,而“文件文件2”又包含又包含“文件文件3”,则,则 可在可在“文件文件1”中使用两个中使用两个include命令。即:命令。即: 文件文件file1.c #include“file3.h” / file3.h应出现在应出现在file2.h之前之前 / #include“file2.h” 文件包含可以嵌套。即一个被包含文件中又可以包含另一个文文件包含可以嵌套。即一个被包
31、含文件中又可以包含另一个文 件。如件。如 : 文件文件file1.c #include“file2.h” 文件文件file2.c #include“file3.h” 6.11 “文件包含文件包含” 处理处理 在在C中可以用中可以用 #include 命令实现一个文件包含另一命令实现一个文件包含另一 个文件。语句形式:个文件。语句形式: #include “文件名文件名” 2021-4-2235 6.12 条件编译条件编译 条件编译的语句形式:条件编译的语句形式: 1#ifdef 标识符标识符 程序段程序段1 #else 程序段程序段2 #endif 其作用是:如果其作用是:如果“标识符标识符”已定义,则编译已定义,则编译“程序段程序段 1”,否则编译,否则编译“程序段程序段2” 。 在在#include命令中,文件名既可用双引命令中,文件名既可用双引“ ”号也可号也可 用尖括号用尖括号括起来。但用双引号更方便系统查找被
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 车辆质押合同模板10篇
- 营养师案例试题及答案
- 学校校园安全隐患大排查大整治实施方案
- 浙江省杭州市萧山区2026年中考模拟英语试卷附答案
- 2025年临床执业医师《临床》卷
- 药品质量管理制度试题及答案
- 医疗机构XX管理制度
- 中职日常考试试题及答案
- 医疗器械经营质量管理规范(GSP)内审培训试题及答案
- 183红色喜庆福字背景的“金龙献瑞”龙年新年主题模板 2
- DB36∕T 1739-2023 养老机构老年人出入院服务规范
- 《药理学》课件-第1章 绪言
- 【《空巢老人的生活现状和服务需求研究-以杭州市XX区为例》9000字(论文)】
- 非结核分枝杆菌病诊断与治疗指南(2025年版)
- 2024-2025学年度南京信息职业技术学院单招《职业适应性测试》模拟试题附参考答案详解(轻巧夺冠)
- GB/T 5563-2025橡胶和塑料软管及软管组合件静液压试验方法
- 上海市经信委课题申报书
- 2024-2025学年度辽宁经济职业技术学院单招数学试题及答案详解一套
- 高压电工安全培训课件
- 哈他瑜伽教学课件
- 铲运机司机岗前考核试卷及答案
评论
0/150
提交评论