C言语教程第五章:函数(4)


二、数组名作为函数参数

  用数组名作函数参数与用数组元素作实参有几点不同:
1. 用数组元素作实参时,只需数组标准和函数的形参变量的标准不同,那么作为下标变量的数组元素的标准也和函数形参变量的标准是不同的。因而, 并不要求函数的形参也是下标变量。 换句话说,对数组元素的处置是按平居变量看待的。用数组名作函数参数时, 则要求形参和绝对应的实参都必需是标准相同的数组,都必需有年夜白的数组申明。当形参和实参二者不不同时,即会产生错误。

2. 在平居变量或下标变量作函数参数时,形参变量和实参变量是由编译琐屑分拨的两个差此外内存单元。在函数调用时产生的值传送是把实参变量的值付与形参变量。在用数组名作函数参数时,不是中止值的传送,即不是把实参数组的每一个元素的值都付与形参数组的各个元素。因为志向上形参数组并不存在,编译琐屑不为形参数组分拨内存。那么,数据的传送是怎样样完成的呢? 在第四章中我们曾先容过,数组名就是数组的首地点。因而在数组名作函数参数时所中止的传送只是地点的传送, 也就是说把实参数组的首地点付与形参数组名。形参数组名获得该首地点之后,也就即是有了实在的数组。志向上是形参数组和实参数组为不同数组,共同拥有一段内存空间。图5.1说熟悉打听这种景遇。图中设a为实参数组,标准为整型。a占有以2000 为首地点的一块内存区。b为形参数组名。当产生函数调用时,中止地点传送, 把实参数 组a的首地点传送给形参数组名b,于是b也获得该地点2000。 于是a,b两数组共同占有以2000 为首地点的一段连续内存单元。从图中还可以看出a和b下标相同的元素志向上也占相同的两个内
存单元(整型数组每个元素占二字节)。例如a[0]和b[0]都占用2000和2001单元,当然a[0]即是b[0]。类推则有a[i]即是b[i]。
[例5.5]数组a中寄存了一个师长教师5门课程的成就,求匀称成就。
float aver(float a[5])
{
int i;
float av,s=a[0];
for(i=1;i<5;i )
s=s a[i];
av=s/5;
return av;
}
void main()
{
float sco[5],av;
int i;
printf("\ninput 5 scores:\n");
for(i=0;i<5;i )
scanf("%f",&sco[i]);
av=aver(sco);
printf("average score is %5.2f",av);
}
float aver(float a[5])
{ ……
}
void main()
{
……
for(i=0;i<5;i )
scanf("%f",&sco[i]);
av=aver(sco);
……
}
  本步调起首定义了一个实型函数aver,有一个形参为实型数组a,长度为5。在函数aver中,把各元素值相加求出匀称值,前往给主函数。主函数main 中起首完成数组sco的输出,然后以sco作为实参调用aver函数,函数前往值送av,末了输出av值。 从运转景遇可以看出,步调完成了所要求的服从

3. 后面已经评论申辩过,在变量作函数参数时,所中止的值传送是单向的。即只能从实参传向形参,不克不及从形参传回实参。形参的初值和实参相同, 而形参的值产生改变后,实参并不厘革, 两者的终值是差此外。例5.3证清楚明晰这个结论。 而当用数组名作函数参数时,景遇则不同。 因为志向上形参和实参为不同数组, 因而当形参数组产生厘革时,实参数组也随之厘革。 当然这种景遇不克不及熟悉打听为产生了“双向”的值传递。但从现终究形来看,调用函数之后实参数组的值把因为形参数组值的厘革而厘革。为了申明这种景遇,把例5.4改为例5.6的方式。[例5.6]题目同5.4例。改用数组名作函数参数。
void nzp(int a[5])
{
int i;
printf("\nvalues of array a are:\n");
for(i=0;i<5;i )
{
if(a[i]<0) a[i]=0;
printf("%d ",a[i]);
}
}
main()
{
int b[5],i;
printf("\ninput 5 numbers:\n");
for(i=0;i<5;i )
scanf("%d",&b[i]);
printf("initial values of array b are:\n");
for(i=0;i<5;i )
printf("%d ",b[i]);
nzp(b);
printf("\nlast values of array b are:\n");
for(i=0;i<5;i )
printf("%d ",b[i]);
}
void nzp(int a[5])
{ ……
}
main()
{
int b[5],i;
……
nzp(b);
……
}
  本步调中函数nzp的形参为整数组a,长度为 5。 主函数中实参数组b也为整型,长度也为5。在主函数中起首输出数组b的值,然后输出数组b的初始值。 然后以数组名b为实参调用nzp函数。在nzp中,按要求把负值单元清0,并输出形参数组a的值。 前往主函数之后,再次输出数组b的值。从运转效果可以看出,数组b 的初值和终值是差此外,数组b 的终值和数组a是相同的。这申明实参形参为不同数组,它们的值同时得以改变。 用数组名作为函数参数时还应垂青以下几点:
a. 形参数组和实参数组的标准必需不同,否则把惹起错误。
b. 形参数组和实参数组的长度可以不相同,因为在调用时,只传送首地点而不反省形参数组的长度。当形参数组的长度与实参数组不不同时,虽不至于呈现语法错误(编译能经由),但步调施行效果把与志向不符,这是应予以垂青的。如把例5.6点窜如下:
void nzp(int a[8])
{
int i;
printf("\nvalues of array aare:\n");
for(i=0;i<8;i )
{
if(a[i]<0)a[i]=0;
printf("%d",a[i]);
}
}
main()
{
int b[5],i;
printf("\ninput 5 numbers:\n");
for(i=0;i<5;i )
scanf("%d",&b[i]);
printf("initial values of array b are:\n");
for(i=0;i<5;i )
printf("%d",b[i]);
nzp(b);
printf("\nlast values of array b are:\n");
for(i=0;i<5;i )
printf("%d",b[i]);
}
  本步调与例5.6步调比,nzp函数的形参数组长度改为8,函数体中,for语句的轮回条件也改为i<8。因而,形参数组 a和实参数组b的长度不不同。编译可以经由,但从效果看,数组a的元素a[5],a[6],a[7]显然是有意义的。c. 在函数形参表中,允许不给出形参数组的长度,或用一个变量来显露数组元素的个数。
例如:可以写为:
void nzp(int a[])
或写为
void nzp(int a[],int n)
  此中形参数组a没有给出长度,而由n值静态地显露数组的长度。n的值由主调函数的实参中止传送。
由此,例5.6又可改为例5.7的方式。
[例5.7]
void nzp(int a[],int n)
{
int i;
printf("\nvalues of array a are:\n");
for(i=0;i<n;i )
{
if(a[i]<0) a[i]=0;
printf("%d ",a[i]);
}
}
main()
{
int b[5],i;
printf("\ninput 5 numbers:\n");
for(i=0;i<5;i )
scanf("%d",&b[i]);
printf("initial values of array b are:\n");
for(i=0;i<5;i )
printf("%d ",b[i]);
nzp(b,5);
printf("\nlast values of array b are:\n");
for(i=0;i<5;i )
printf("%d ",b[i]);
}
void nzp(int a[],int n)
{ ……
}
main()
{
……
nzp(b,5);
……
}
  本步调nzp函数形参数组a没有给出长度,由n 静态确定该长度。在main函数中,函数调用语句为nzp(b,5),此中实参5把付与形参n作为形参数组的长度。
d. 多维数组也可以作为函数的参数。 在函数定义时对形参数组可以指定每一维的长度,也可省去第一维的长度。因而,以下写法都是合法的。
int MA(int a[3][10])

int MA(int a[][10])



版权声明: 原创作品,允许转载,转载时请务必以超链接方式标明文章 原始出处 、作者信息和本声明。否则将清查执法责任。

原文地址:https://www.cnblogs.com/zgqjymx/p/1975601.html