间)
实参地址形参地址
调用函数实参:一般是数组名或指针变量 四、函数调用及值的返回 1.函数调用
格式: 函数名 (实参表列); 调用的过程:
a)通过函数名,找到定义的函数
b)将实际参数传递给被调函数的形式参数
(实际参数与形式参数一一对应,既一一传递数据) 许多C版本是按自右而左的顺序求值 例:P150 例8.4 main ( ) { int i=2, p。
p=f(i, ++i) 。/* f为f(3, 3) */ printf ( “%d” , p )。 }
int f(int a , b) { int c。
if (a>b) c=1。
else if (a= =b) c=0。 else c= -1。 return( c )。
} 运行结果:0
说明:(1)应避免这种情况的产生,可写为: ①自左而右顺序 ②自右而左顺序 j=i。 j=++i。
k=++i。 p=f(j, j)。 p=f(j, k)。
(2)在printf(“ %d, %d ”,i, i++)。 中同样存在 当:i=3; 结果为: 4,3 2.函数调用的几种方式
(1)函数语句 把函数调用作为一个语句,即单独一个语句行。 不要求函数带回值,只要求函数完成一定操作。 即:printstar( )。
(2)函数表达式 函数出现在一个表达式中,要求函数带回一个确 定的值以参加表达式的运算。 即:c=2*max( a, b )。
(3)函数参数 函数调用作为一个函数的实参; 即:m=max(a,max(b, c));
3.函数说明
作用:在函数使用前对函数的特征进行说明的语句。(用户自定义函数)
? 对已定义的函数的返回值进行类型说明。 ? 告诉系统在本函数中将要用到的函数是什么类型。 ? C语言规定:以下几种情况可以不使用函数说明 a)函数的值(函数的返回值)是整型或字符型(系统自动按整说明) b)如果函数定义在调用函数之前,可以不必加以说明 在函数说明和函数定义中: a)类型定义、函数名要相同 b)形式参数标识符可以不相同 如:main ( ) {
double abc ( int x , float y ) 。/*函数说明*/ --- }
double abc ( int a , float b ) /*函数定义 a,b与x,y不同*/ 函数体 }
非int形参的函数必须在调用前进行函数说明P148 例8.3、8.5 不使用函数说明例子
例:main ( )float abc ( float x , float y )
{int sum , a=2 , b=5。{x=x+y。 定 sum=add( a , b ) 。 return(x)。义 ┄}
} main ( )
int add( int x , int y ) { float sum , a=2.0 , b=5.0。 { x=x+y。 定义 sum=abc( a , b )。 return (x) 。 语句 } }
说明:使用库函数,一般在文件开头用#include命令 即:#include “math.h” main () { … a=sqrt(x) … }
4.函数的嵌套调用
1)C语言函数不能嵌套定义即:函数定义 函数定义 函数定义1
函数定义2 各个函数定义是互相平行的
函数定义3
2)C函数允许嵌套调用,即在调用一个函数的过程中,又调用另一个函数。
main ( )a函数 b函数 调用b函数 调用a函数 返回 结束 返回
示例:
*五、递归调用
一个函数自己调用自己的过程
递归:由递归方式与递归终止条件两部分组成 即:一个递归的问题可以分为:首先“回推”,然后“递推” 在递归过程中,必须具有一个结束递归过程的条件。 例:N! 1 (N=0, 1) 递归公式=
N*(N-1)! (N>1) 子函数定义 求:4!
long fac( int n ) sum=fac(4)结束条件。 { long fa。 if (n= =0) fa=1 else fa=n*fac(n-1)。 return(fa)。}
第一步 fac(4)fa=4*fac(4-1)=4*fac(3) fa=4*3*2*1*1 第二步 fac(3)fa=3*fac(3-1)=3*fac(2) fa=3*2*1*1 第三步 fac(2)fa=2*fac(2-1)=2*fac(1) fa=2*1*1 第四步 fac(1)fa=1*fac(1-1)=1*fac(0) fa=1*1 第五步 fac(0)fa=1
递推 回推
六、函数参数的使用(实参或形参)
? 实参:在调用函数中; 形参:在函数定义中
? 函数参数:1)数值 2)变量 3)数组元素 4)数组名 5)指针 1.函数间的参数传递 (1)数值传递方式 实参地址形参地址
调用函数的实参:给出具体数据 主要是:1)数值 2)变量 3)数组元素 (2)地址传递方式 实参地址形参地址
主要是:调用函数实参:一般是数组名或指针变量 2.数组有两种参数:
a) 数组元素:一个数组元素相当于一个变量,所以,数组元素可以用于函数参数,用法与变量相同。 是传递数据方式 b) 数组名:数组名作为一个变量用于函数实参和形参,传递的是整个数组元素或部分数据元素。 是传递地址方式
(1)数组元素作实参的传值调用
? 把数组元素当作变量来作为实参使用 ? 传值调用最多返回一个值
例: main ( ) { int a[5]。
调用函数 …
a[0]=mul( a[1] , a[4] ) 。 …
函数定义 }
int mul(int x , int y ) { int s 。 …
return( s )。 }
(2)数组名作函数参数(实参与形参都用数组名) 具有:存贮地址作实参的传址调用 例: (J5_3.C) main ()
{ void swap(float x[2])。 float a[2]={10.5,2.7}。
printf(\。 swap(a)。
printf(\。 }
void swap(float x[2]) 相当于: void swap( x) { float t。 { float x[2]。 t=x[0]。x[0]=x[1]。x[1]=t。 }
说明:a)数组名在主调函数和被调函数中,分别进行定义,并且类型一致。
b)调用的实质: 数组a和数组x
数组a独享存贮区共享存贮区 数组a独享存贮区
10.5 2.7 2.7 2.7 10.5 10.5
c)实参数组和形参数组大小可以不一致
(C语言编译时,对形参数组大小不作检查,只是将实参数组的首地址传给形参数组,这样两个数组共同占用同一段内存单元) 例 (J5_4.C) main ()
{ void fun(float x[4])。
float a[4]={3.5,6.1,0.2,7.9}。