靳润昭C语言教程讲义 2001年2月17日 或者为 return(表达式) 该语句的功能是计算表达式的值,并返回给主调函数。在函数中允许有多个 return 语句,但每次调用只能有一个 return语句被执行,因此只能返回一个函数值 函数值的类型和函数定义中函数的类型应保持一致。如果两者不一致,则以函数类 型为准,自动进行类型转换 3)如函数值为整型,在函数定义时可以省去类型说明。 4)不返回函数值的函数,可以明确定义为“空类型”,类型说明符为“void"。如例 8.2中函数s并不向主函数返函数值,因此可定义为: void s(int n) 旦函数被定义为空类型后,就不能在主调函数中使用被调函数的函数值了 例如,在定义s为空类型后,在主函数中写下述语句 sum=s(n) 就是错误的 为了使程序有良好的可读性并减少出错,凡不要求返回值的函数都应定义为 空类型 84函数的调用 841函数调用的一般形式 前面己经说过,在程序中是通过对函数的调用来执行函数体的,其过程与其它语言的子 程序调用相似。 C语言中,函数调用的一般形式为 函数名(实际参数表) 对无参函数调用时则无实际参数表。实际参数表中的参数可以是常数,变量或其它构造 类型数据及表达式。各实参之间用逗号分隔 842函数调用的方式 在C语言中,可以用以下几种方式调用函数 1.函数表达式:函数作为表达式中的一项出现在表达式中,以函数返回值参与表达式的运 算。这种方式要求函数是有返回值的。例如:z=max(x,y)是一个赋值表达式,把max 的返回值赋予变量z。 2.函数语句:函数调用的一般形式加上分号即构成函数语句。例如: ("%d",a); scanf("%d",&b);都是以函数语句的方式调用函数 3.函数实参:函数作为另一个函数调用的实际参数出现。这种情况是把该函数的返回值作 为实参进行传送,因此要求该函数必须是有返回值的。例如: printf("%d",max(x,y);即是把max调用的返回值又作为 printf函数的实参来使 用的。在函数调用中还应该注意的一个问题是求值顺序的问题。所谓求值顺序是指对实 第6页
靳润昭 C 语言教程讲义 2001 年 2 月 17 日 第6页 或者为: return (表达式); 该语句的功能是计算表达式的值,并返回给主调函数。在函数中允许有多个 return 语句,但每次调用只能有一个 return 语句被执行,因此只能返回一个函数值。 2) 函数值的类型和函数定义中函数的类型应保持一致。如果两者不一致,则以函数类 型为准,自动进行类型转换。 3) 如函数值为整型,在函数定义时可以省去类型说明。 4) 不返回函数值的函数,可以明确定义为“空类型”,类型说明符为“void”。如例 8.2 中函数 s 并不向主函数返函数值,因此可定义为: void s(int n) { …… } 一旦函数被定义为空类型后,就不能在主调函数中使用被调函数的函数值了。 例如,在定义 s 为空类型后,在主函数中写下述语句 sum=s(n); 就是错误的。 为了使程序有良好的可读性并减少出错, 凡不要求返回值的函数都应定义为 空类型。 8.4 函数的调用 8.4.1 函数调用的一般形式 前面已经说过,在程序中是通过对函数的调用来执行函数体的,其过程与其它语言的子 程序调用相似。 C语言中,函数调用的一般形式为: 函数名(实际参数表) 对无参函数调用时则无实际参数表。实际参数表中的参数可以是常数,变量或其它构造 类型数据及表达式。各实参之间用逗号分隔。 8.4.2 函数调用的方式 在C语言中,可以用以下几种方式调用函数: 1. 函数表达式:函数作为表达式中的一项出现在表达式中,以函数返回值参与表达式的运 算。这种方式要求函数是有返回值的。例如:z=max(x,y)是一个赋值表达式,把 max 的返回值赋予变量 z。 2. 函数语句:函数调用的一般形式加上分号即构成函数语句。例如: printf ("%d",a);scanf ("%d",&b);都是以函数语句的方式调用函数。 3. 函数实参:函数作为另一个函数调用的实际参数出现。这种情况是把该函数的返回值作 为 实 参 进 行 传 送 , 因 此 要 求 该 函 数 必 须 是 有 返 回 值 的 。 例 如 : printf("%d",max(x,y)); 即是把 max 调用的返回值又作为 printf 函数的实参来使 用的。在函数调用中还应该注意的一个问题是求值顺序的问题。所谓求值顺序是指对实
靳润昭C语言教程讲义 2001年2月17日 参表中各量是自左至右使用呢,还是自右至左使用。对此,各系统的规定不一定相同 介绍 printf函数时已提到过,这里从函数调用的角度再强调一下 【例8.3】 main int i=8 printf("%d\n%d\n%dn%dn”,+i,一i,i++,i-) 如按照从右至左的顺序求值。运行结果应为 778 如对 printf语句中的++i,-i,i++,i一从左至右求值,结果应为 9889 应特别注意的是,无论是从左至右求值,还是自右至左求值,其输出顺序都是不变的, 即输出顺序总是和实参表中实参的顺序相同。由于 Turbo C现定是自右至左求值,所以结果 为8,7,7,8。上述问题如还不理解,上机一试就明白了 843被调用函数的声明和函数原型 在主调函数中调用某函数之前应对该被调函数进行说明(声明),这与使用变量之前要 先进行变量说明是一样的。在主调函数中对被调函数作说明的目的是使编译系统知道被调函 数返回值的类型,以便在主调函数中按此种类型对返回值作相应的处理。 其一般形式为: 类型说明符被调函数名(类型形参,类型形参.) 或为 类型说明符被调函数名(类型,类型) 括号内给出了形参的类型和形参名,或只给出形参类型。这便于编译系统进行检错,以 防止可能出现的错误 例8.1main函数中对max函数的说明为: int max(int a, int b) 或写为 int max(int, int) C语言中又规定在以下几种情况时可以省去主调函数中对被调函数的函数说明。 1)如果被调函数的返回值是整型或字符型时,可以不对被调函数作说明,而直接调用 这时系统将自动对被调函数返回值按整型处理。例8.2的主函数中未对函数s作说 明而直接调用即属此种情形。 2)当被调函数的函数定义出现在主调函数之前时,在主调函数中也可以不对被调函数 第7页
靳润昭 C 语言教程讲义 2001 年 2 月 17 日 第7页 参表中各量是自左至右使用呢,还是自右至左使用。对此,各系统的规定不一定相同。 介绍 printf 函数时已提到过,这里从函数调用的角度再强调一下。 【例 8.3】 main() { int i=8; printf("%d\n%d\n%d\n%d\n",++i,--i,i++,i--); } 如按照从右至左的顺序求值。运行结果应为: 8 7 7 8 如对 printf 语句中的++i,--i,i++,i--从左至右求值,结果应为: 9 8 8 9 应特别注意的是,无论是从左至右求值, 还是自右至左求值,其输出顺序都是不变的, 即输出顺序总是和实参表中实参的顺序相同。由于 Turbo C 现定是自右至左求值,所以结果 为 8,7,7,8。上述问题如还不理解,上机一试就明白了。 8.4.3 被调用函数的声明和函数原型 在主调函数中调用某函数之前应对该被调函数进行说明(声明),这与使用变量之前要 先进行变量说明是一样的。在主调函数中对被调函数作说明的目的是使编译系统知道被调函 数返回值的类型,以便在主调函数中按此种类型对返回值作相应的处理。 其一般形式为: 类型说明符 被调函数名(类型 形参,类型 形参…); 或为: 类型说明符 被调函数名(类型,类型…); 括号内给出了形参的类型和形参名,或只给出形参类型。这便于编译系统进行检错,以 防止可能出现的错误。 例 8.1 main 函数中对 max 函数的说明为: int max(int a,int b); 或写为: int max(int,int); C语言中又规定在以下几种情况时可以省去主调函数中对被调函数的函数说明。 1) 如果被调函数的返回值是整型或字符型时,可以不对被调函数作说明,而直接调用。 这时系统将自动对被调函数返回值按整型处理。例 8.2 的主函数中未对函数 s 作说 明而直接调用即属此种情形。 2) 当被调函数的函数定义出现在主调函数之前时,在主调函数中也可以不对被调函数
靳润昭C语言教程讲义 2001年2月17日 再作说明而直接调用。例如例8.1中,函数max的定义放在main函数之前,因此 可在main函数中省去对max函数的函数说明 int max(inta,intb) 3)如在所有函数定义之前,在函数外预先说明了各个函数的类型,则在以后的各主调 函数中,可不再对被调函数作说明。例如 char str(int a) float f(float b) maino char str(int a) float f(float b) 其中第一,二行对str函数和f函数预先作了说明。因此在以后各函数中无须对 str和f函数再作说明就可直接调用。 4)对库函数的调用不需要再作说明,但必须把该函数的头文件用 include命令包含在 源文件前部。 8.5函数的嵌套调用 C语言中不允许作嵌套的函数定义。因此各函数之间是平行的,不存在上一级函数和下 级函数的问题。但是C语言允许在一个函数的定义中出现对另一个函数的调用。这样就出 现了函数的嵌套调用。即在被调函数中又调用其它函数。这与其它语言的子程序嵌套的情形 是类似的。其关系可表示如图。 main函数a函数b函数 调用a函数调用b函数 结束 图表示了两层嵌套的情形。其执行过程是:执行main函数中调用a函数的语句时,即 转去执行a函数,在a函数中调用b函数时,又转去执行b函数,b函数执行完毕返回a 函数的断点继续执行,a函数执行完毕返回main函数的断点继续执行。 第8页
靳润昭 C 语言教程讲义 2001 年 2 月 17 日 第8页 再作说明而直接调用。例如例 8.1 中,函数 max 的定义放在 main 函数之前,因此 可在 main 函数中省去对 max 函数的函数说明 int max(int a,int b)。 3) 如在所有函数定义之前,在函数外预先说明了各个函数的类型,则在以后的各主调 函数中,可不再对被调函数作说明。例如: char str(int a); float f(float b); main() { …… } char str(int a) { …… } float f(float b) { …… } 其中第一,二行对 str 函数和 f 函数预先作了说明。因此在以后各函数中无须对 str 和 f 函数再作说明就可直接调用。 4) 对库函数的调用不需要再作说明,但必须把该函数的头文件用 include 命令包含在 源文件前部。 8.5 函数的嵌套调用 C语言中不允许作嵌套的函数定义。因此各函数之间是平行的,不存在上一级函数和下 一级函数的问题。但是C语言允许在一个函数的定义中出现对另一个函数的调用。这样就出 现了函数的嵌套调用。即在被调函数中又调用其它函数。这与其它语言的子程序嵌套的情形 是类似的。其关系可表示如图。 图表示了两层嵌套的情形。其执行过程是:执行 main 函数中调用 a 函数的语句时,即 转去执行 a 函数,在 a 函数中调用 b 函数时,又转去执行 b 函数,b 函数执行完毕返回 a 函数的断点继续执行,a 函数执行完毕返回 main 函数的断点继续执行