第5章模块化程序设计 5.1概述 5.7局部变量和全局变量 5.2函数定义的一般形式58动态存储变量与静态存储变量 5.3函数参数和函数的值59内部函数和外部函数 54函数的调用 5.10编译预处理 5.5函数的嵌套调用 511文件包含”处理 5.6函数的递归调用 5.12条件编译
第 5 章 模块化程序设计 5.1 概述 5.2 函数定义的一般形式 5.3 函数参数和函数的值 5.4 函数的调用 5.5 函数的嵌套调用 5.6 函数的递归调用 5.7 局部变量和全局变量 5.8 动态存储变量与静态存储变量 5.9 内部函数和外部函数 5.10 编译预处理 5.11 “文件包含” 处理 5.12 条件编译
第5章模块化程序设计 51概述 在进行程序设计时,程序员总是将复杂的问题进行 分解,化整为零。编写一段小程序就能解决一个小问题, 然后将这些小程序拼装起来就能解决非常大而复杂的问 题。在C中,这些小程序统称为函数。 在C中,由系统提供的函数放在函数库中供用户选 用,以减少重复编写程序模块的工作量。 ①所有函数都是平行的,相互独立不能嵌套,但可以相 互调用。 ②c函数分标准函数库函数和自定义函数。 ③c函数本身分有参函数和无参函数
第 5 章 模块化程序设计 在进行程序设计时,程序员总是将复杂的问题进行 分解, 化整为零。编写一段小程序就能解决一个小问题, 然后将这些小程序拼装起来就能解决非常大而复杂的问 题。在 C 中,这些小程序统称为函数。 在 C 中,由系统提供的函数放在函数库中供用户选 用,以减少重复编写程序模块的工作量。 所有函数都是平行的,相互独立不能嵌套,但可以相 互调用。 C 函数分标准函数(库函数)和自定义函数。 C 函数本身分有参函数和无参函数。 5.1 概述
52函数定义的一般形式 1.无参函数的定义形式 类型标识符函数名() 【说明部分; 语句; 无参函数一般不需要返回函数值,可以省略类型标识符。 2.有参函数的定义形式 类型标识符函数名形式参数表) 形式参数说明; 说明部分; 语句
5.2 函数定义的一般形式 1.无参函数的定义形式 类型标识符 函数名( ) { 说明部分 ; 语句; } 无参函数一般不需要返回函数值,可以省略类型标识符。 2.有参函数的定义形式 类型标识符 函数名(形式参数表) 形式参数说明; { 说明部分 ; 语句; }
例: int max(x,y) int X, yi /*形式参数说明* f int z *函数体中的说明部分* Z=Xy ?x: y return (z) 这两行可以写成一行: int max(int x, int 3.“空函数 类型说明符函数名() “空函数”什么操作也不做。其作用是在此处留一函数的 位置,以便将来扩充功能之用。函数名也在将来换取实 际的函数名
例: int max(x,y) int x, y; / 形式参数说明 / { int z; / 函数体中的说明部分 / z=x>y ? x : y; return(z); } 类型说明符 函数名( ) { } “空函数”什么操作也不做。其作用是在此处留一函数的 位置,以便将来扩充功能之用。函数名也在将来换取实 际的函数名。 这两行可以写成一行: int max(int x, int y) 3.“ 空函数
53函数参数和函数的值 1.形式参数和实际参数 例51从键盘输入两个数,输出其中较大的一个。 main( f int a, b,C, scanf("%d, d,,&a, &b C=max(a, b); *a,b为实际参数* printf(( Max is%d”,c); max(x,y) *x,y为形式参数* int X, yy f int z=X>y x: y; return (z);
5.3 函数参数和函数的值 1.形式参数和实际参数 例5.1 从键盘输入两个数,输出其中较大的一个。 main( ) { int a, b, c ; scanf(“%d,%d”, &a, &b); c=max(a,b); / a, b为实际参数 / printf(“Max is %d”,c); } max(x,y) / x, y为形式参数 / int x, y; { int z; z=x>y ? x : y; return(z); }
注意: ①形参变量在被调用前不占用存储单元;在被调用结束 后,形参所占存储单元亦被释放。 ②实参可以是常量、变量或表达式。 ③必须指定形参类型,且必须与实参的类型一致。 ④实参对形参的数据传递是“值传递”。即单向传递, 能逆传。 ⑤可以在形参表中直接说明形参类型。如: int max(int x, int y); float fun(int a[10], int n);
注意: 形参变量在被调用前不占用存储单元;在被调用结束 后,形参所占存储单元亦被释放。 实参可以是常量、变量或表达式。 必须指定形参类型,且必须与实参的类型一致。 实参对形参的数据传递是“值传递”。即单向传递,不 能逆传。 可以在形参表中直接说明形参类型。如: int max(int x, int y); float fun(int a[10], int n);
2.函数的返回值 ①函数的返回值是通过 return语句获得的。当不需返 回函数值时,可省去 return语句。 ② return语句的后面可以有括号,也可以没有。如: return z;冷 return(z); ③ return语句的后面可以是变量,也可以是表达式。如: return(x >y x: y); ④ return语句返回值的类型应与该函数的类型一致。 否则以函数类型为准
2.函数的返回值 函数的返回值是通过return语句获得的。当不需返 回函数值时,可省去return语句。 return语句的后面可以有括号,也可以没有。如: return z; return(z); return语句的后面可以是变量,也可以是表达式。如: return(x >y ? x : y); return语句返回值的类型应与该函数的类型一致。 否则以函数类型为准
⑤若函数中没有 return语句,则该函数被调用后也会带 回不确定的值。如: iint a, b, C, a= printstar(); 均为处理字符串的函数 b= print_message();/且均没有reun语句 c= printstar(; printf("%d, %d, %dIn",a,b, c); 输出的a,b,c的值将是各个被处理的字符串的长度 ⑥为了明确表示不需要函数返回值,可以用“vod定义 函数为无类型”。此时,不得使用a= printstar()之 类的语句。 凡不需要返回值的函数,一般均定义为“vod”类型
若函数中没有return语句,则该函数被调用后也会带 回不确定的值。 { int a, b, c ; a = printstar( ); b = print_message( ); c = printstar( ); printf(“%d,%d,%d\n”,a,b,c); } 输出的a, b, c的值将是各个被处理的字符串的长度。 为了明确表示不需要函数返回值,可以用“void”定义 函数为 “无类型”。此时,不得使用 a=printstar( ) 之 类的语句。 凡不需要返回值的函数,一般均定义为“void”类型。 如: 均为处理字符串的函数 且均没有 return 语句
54函数的调用 1.函数调用的一般形式 函数名(实参表) 说明 ①对于无参函数,尽管没有“实参表”,但也不得省略 括号 ②“实参表”中的参数之间用逗号分开。 ③实参与形参之间的个数及类型必须一一对应。 ④对实参求值的顺序是自左至右还是自右至左,视具体 的系统而定。 Turbo c和Msc是按自右至左的顺 序求值
5.4 函数的调用 1.函数调用的一般形式 函数名(实参表) 说明: 对于无参函数,尽管没有“实参表”,但也不得省略 括号。 “实参表”中的参数之间用逗号分开。 实参与形参之间的个数及类型必须一一对应。 对实参求值的顺序是自左至右还是自右至左, 视具体 的系统而定。Turbo C 和 MS C 是按自右至左的顺 序求值
例52 main( 注意:这里是按自右至左求 i int i=2.p 值的,相当于fun(33)若 p=f(,(++i; 按自左至右求值,则相当于 printf/d,; fun(2,3),则输出为-1。 int f(a, b), 先执行++使i的值为3 int a. b 然后将i的值3传递给a iint c if (a>b)C=1;1 a的值为3,b的值为3 else if (a==b)C=0; else c==1 return(c) 输出结果 0
例5.2 main( ) { int i =2 , p ; p = f( i, ++i ); printf ( “%d”, p ) ; } int f(a, b ) ; int a, b ; { int c ; if ( a > b ) c = 1; else if ( a == b ) c = 0 ; else c = –1 ; return( c ) ; } 输出结果: 0 注意: 这里是按自右至左求 值的,相当于 fun(3,3)。若 按自左至右求值,则相当于 fun(2,3), 则输出为–1。 先执行++i 使 i 的值为3 再将 i 的值 3 传递给 b b的值为3 然后将 i 的值 3 传递给a a的值为3