知识要点:函数的参数及返回值和函数的调用及声明
视频:
目录
一、任务分析
二、必备知识与理论
三、任务实施
一、任务分析
1.求x的n次方的值也就是求n个x的乘积,可把x和n作为函数的形参,定义一个函数power来完成这个功能;
2.主调函数里提供实参,通过函数调用将实参的值传递给形参,调用完成后,power函数将所求的x的n次方的值作为返回值返回主调函数;
3.数据从主调函数里传递,可以增加程序的灵活性。
二、必备知识与理论
1.函数的参数
函数的参数用于建立函数之间的数据联系。当一个函数调用另一个函数时,实际参数的值会传递给形式参数,以实现主调函数与被调函数之间的数据通信。同时,函数参数的运用还可以提高函数的灵活性和通用性。
(1)形式参数和实际参数
形式参数(简称形参)是指在定义函数时,跟在函数名后面的小括号中的变量名。实际参数(简称实参)是指调用函数时,跟在函数名后面的小括号中的表达式。
(2)参数的传递
在调用函数时,主调函数和被调函数之间有数据的传递——实参传递给形参。
关于形参与实参的说明:
(1)在定义函数中指定的形参变量,在未出现函数调用时,它们并不占内存中的存储单元。只有在发生函数调用时,函数中的形参才被分配内存单元。在调用结束后,形参所占的内存单元也被释放。
(2)实参可以是常量、变量、表达式、函数等,无论实参是何种类型的变量,在进行调用时,它们都必须具有确定的值,以便在调用时将实参的值赋给形参,因此,实参在使用前必须事先赋值。
(3)实参和形参,名称可相同也可不同,但实参与形参的类型应一致,参数个数、对应顺序上也必须保持一致,否则,会发生“类型不匹配”的错误。在C语言中,字符型数据与0~255之间的整型数据可以互相通用。
(4)实参向形参传递数据,有两种方式:
①数值传递,也称传数值,如常量值、变量值、表达式值、数组元素值、函数值等,这些值都是由用户程序决定。
②地址传递,也称传地址,如变量地址、指针、数组名所代表的地址等,值由系统分配决定,用户不能指定。当然,地址也是数值,是一个地址数据值。
③数值传递和地址传递的区别:只是传递的数据类型不同。
(5)实参变量对形参变量的数值传递属于单向传递,只由实参传给形参,而不能由形参传回来给实参。
(6)函数调用,如果是数值传递,传递后实参仍保留原值并不改变。如果是地址传 递,传递后实参地址的值也不会改变,但地址的内容可能会改变。
2.函数的返回值
通常,希望通过函数调用使主调函数能得到一个确定的值,这就是函数的返回值。下面对函数值作一些说明:
(1) return语句:函数的返回值是通过函数中的return语句获得的。return语句的一般形式为:
return(表达式);
return语句将被调用函数中的一个确定值带回主调函数中,如果需要从被调用函数带回一个函数值(供主调函数使用),被调用函数中必须包含return语句。如果不需要从被调用函数带回函数值可以不要return语句。
①return语句后面的括弧也可以不要,如“return(z);”与“return z;”等价。
②return后面的值可以是一个表达式,例如:任务一中的max函数可以改写为:
max(int x,int y)
{
return(x>y?x:y);
}
这样的函数体更为简短,return语句的功能是计算表达式的值,并返回给主调函数。
③在函数中允许有多个return语句,但要求每个return后面的表达式的类型应相同。每次调用只能有一个return 语句被执行,因此只能返回一个函数值。
④如果被调函数中没有return语句,并不带回一个确定的、用户所希望得到的函数值,但实际上,函数并不是不带回值,而只是不带回有用的值,带回的是一个不确定的值。
(2)函数值的类型。既然函数有返回值,这个值当然应属于某一个确定的类型,应当在定义函数时指定函数值的类型。例如:
int max(int x,int y) /* 函数值为整型 */
double min(int x,int y) /*函数值为双精度型*/
C语言规定,凡不加类型说明的函数,一律自动按整型处理。为了便于以后代码在不同编译环境下重复使用,建议在定义时对所有的函数都要指定函数类型。
(3)在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致。如果两者不一致,则以函数类型为准。对数值型数据,可以自动进行类型转换。即函数类型决定返回值的类型。
(4)对于“不带回值”的函数,应当使用“void”定义为“空类型”。这样,系统就保证在函数中不能使用return带回任何值。但系统仍然允许void类型函数使用return语句,此时语句的作用是结束函数的运行,返回到主调函数。
3.函数的调用
(1)函数调用的一般形式
函数定义一旦完成,我们就可以通过函数名来调用函数,执行函数体的内容,其过程与其它语言的子程序调用相类似。C语言中,函数调用的一般形式为:
函数名(实际参数表列);
如果是调用无参函数,则实参表列可以没有,但括号不能省略。实参表列中的参数可以是常量、变量或其它构造类型数据及表达式。如果实参表列包含多个实参,则各实参之间用逗号分隔。实参与形参的个数应相等,类型应匹配。实参与形参按顺序一一对应传递数据。
(2)函数调用的方式
在C语言中,按照函数在程序中出现的位置,函数的调用方式有三种:
①函数表达式:
②函数语句:
③函数实参:
4.函数的声明
(1)对被调用函数的声明在主调函数中调用另一函数(即被调用函数)需要满足如下条件:
①首先被调用的函数必须是已经存在的函数(是库函数或用户自己定义的函数)。
②如果使用库函数,一般还应该在本文件开头用#include命令将调用有关库函数时所需用到的信息包含到本文件中来。例如,前面已经使用过的命令:
#include <stdio.h> 也可以写成 #include "stdio.h"
③如果使用用户自己定义的函数,而且该函数与主调函数在同一个文件中,一般还 应该在主调函数中对被调函数作声明,即向编译系统声明将要调用此函数,并将有关信息通知编译系统。
(2)函数声明的形式
从程序中可以看到对函数的声明与函数定义首部基本上是相同的,只差一个分号,因此可以简单地照写已定义的函数的首部,再加一个分号,就成为了对函数的“声明”。
函数声明的一般形式为:
函数类型 函数名(参数类型1,参数类型2,…,参数类型n);
函数类型 函数名(参数类型1 形参1,参数类型2 形参2,…,参数类型n 形参n);
其中,第一种形式是基本的形式。为了便于阅读程序,也允许在函数原型中加上参数名,就成了第二种形式。但编译系统不检查参数名,因此参数名是什么都无所谓,并不要求和函数的定义处保持一致。
(3)函数声明的位置:
三、任务实施
编写一函数,求x的n次方的值,其中n是整数。
算法分析:
(1)求x的n次方的值也就是求n个x的乘积,可把x和n作为函数的形参,定义一个函数power来完成这个功能。
(2)主调函数里提供实参,通过函数调用将实参的值传递给形参,调用完成后,power函数将所求的x的n次方的值作为返回值返回主调函数。
(3)power函数中用循环结构来实现该算法。
#include <stdio.h>
long power(int x,int n) /* 函数定义 */
{ int i;
long p=1;
for(i=1;i<=n;i++)
p*=x;
return p;
}
main() /* 主调函数 */
{ int x,n;
long y;
printf("Enter two numbers: x,n!\n");
scanf("%d,%d",&x,&n);
y=power(x,n); /* 函数调用 */
printf("Value=%ld\n",y);
}
运行结果如下:
Enter two numbers: x,n!
2,10↙
Value=1024
注意:本程序中power函数的定义在主调函数main之前,所以在程序中省略了对power函数的声明。