调用有参函数时,需要提供实参,
实参可以是常量、变量或表达式。
数组元素的作用与变量相当,一般来说,凡是变量可以出现的地方,都可以用数组元素代替。
因此,数组元素也可以用作函数实参,其用法与变量相同,向形参传递数组元素的值。
此外,数组名也可以用作形参和实参,传递的是数组第一个元素的地址。
数组元素作函数实参
数组元素可以用作函数实参,但不可以用作形参。
因为形参是在函数被调用时临时分配存储单元的,不可能为一个数组元素单独分配存储单元(数组是一个整体,在内存中占连续的一段存储单元)
在用数组元素做函数实参时,把实参的值传给形参,是”值传递“方式。
数据传递的方向是从实参传到形参,单向传递。
下面我们来看一个程序:
输入10个数,要求输出其中最大的,并说出该数是第几个数。
#include <stdio.h>
int main()
{
int max(int x, int y);
int a[10], m, n, i;
for (i = 0; i < 10; i++)
scanf("%d", &a[i]);
printf("\n");
for (i = 1, m = a[0], n = 0; i < 10; i++)
{
if (max(m, a[i] > m))
{
m = max(m, a[i]);
n = i;
}
}
printf("最大的数是%d\n在第%d个数",m, n + 1);
return 0;
}
int max(int x, int y)
{
return(x > y ? x : y);
}
这个程序先对数组进行赋值,使用for循环
之后就是进行比较,拿第一个数和第二个数比较,选出大的数,与第三个数进行比较,
如是类推,一直比较完,而对应的位置也是不会改变的。
一维数组名作函数参数
数组名也可以作函数参数,形参和实参都可以。
在这里我们来区分一下用数组元素作实参和数组名作函数实参:
用数组元素作实参时,向形参变量传递的是数组元素的值;
用数组名作函数实参时, 向形参(数组名或指针变量)传递的是数组首元素的地址。
这里我们继续来举一个例子。
程序:有一个一维数组score,内存10个学生成绩,求平均成绩。
我们先来看一下代码:
#include <stdio.h>
int main()
{
float average(float array[10]);
float score[10],aver;
int i;
printf("input 10 scores:\n");
for(i=0;i<10;i++)
scanf("%f",&score[i]);
printf("\n");
aver=average(score);
printf("average score is %5.2f\n",aver);
return 0;
}
float average(float array[10])
{
int i;
float aver,sum=array[0];
for(i=1;i<10;i++)
sum=sum+array[i];
aver=sum/10;
return(aver);
}
这段代码利用了函数的调用,包含形参和实参。
下面的函数就是求平均值的函数,通过循环来带入数组中的每一个元素参与运算。
这里面数组名就是做了函数的参数,
我们在用数组名作函数参数时,应该在主调函数和被调用函数分别定义数组
在上面的程序中,array是形参数组名,score是实参数组名。
他们需要分别在其所在函数中定义,不能只在一方定义。
在这个程序中,主调函数的作用是给数组赋值和输出平均值,
被调用函数的作用就是求平均值。
在主调函数中,对数组元素进行声明,
用循环来对数组元素进行赋值。
被调用函数先利用循环求出十个元素的总和,再进行求值。
这里面我们需要注意,
实参数组和形参数组的类型需要保持一致,否则将会出错。
上面的程序中,我们对average函数进行了如下声明:
float average(float array[10])
这里声明了形参数组array的大小是10,
但是在实际上,这个指定大小没有必要,不起任何作用,实际大小可以根据实参来确定。
形参数组可以不指定大小,在定义数组时在数组名后面跟一个空的方括号。
如:
float average(float array[])。
因为在C语言编译系统中,并不检查形参数组的大小,
只是将实参数组的首元素的地址传给形参数组名。
下面的图片可以用来理解:
数组名代表了数组的首元素的地址,
形参数组名获得了实参数组的首元素的地址,
那么就可以认为形参数组首元素(array[0])和实参数组首元素(score[0])具有同一地址。
他们共同占有同一存储单元。
score[n]和array[n]指的是同一单元,
score[n]和array[n]具有相同的值。
相当于是一一对应。
在对源程序进行编译时,
编译系统把形参数组处理为指针变量
就像是上面的float array[]就被转换成了float *array。
这个指针变量就是用来接收从实参数组传过来的地址。
在C语言中,允许使用指针变量或数组作为形参,他们二者时等价关系。
同时,对数组元素的访问,用下标法和指针法也是完全等价的。
我们用形参数组是因为比较容易理解,在形式上是一一对应的。
下面我们来看另一个程序:
有两个班级,分别有5名和10名学生,调用一个average函数,分别求这两个班的学生的平均成绩。
#include <stdio.h>
int main()
{
float average(float array[],int n);
float score1[5]={98.5,97,91.5,60,55};
float score2[10]={67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5};
printf(" The average of class A is %6.2f\n",average(score1,5));
printf(" The average of class B is %6.2f\n",average(score2,10));
return 0;
}
float average(float array[],int n)
{
int i;
float aver,sum=array[0];
for(i=1;i<n;i++)
sum=sum+array[i];
aver=sum/n;
return(aver);
}
这个程序还是很简单的,
主函数先输入两个数组的元素,注意声明的格式,求平均值可能会出现小数,就用了float型。
之后是用了两个printf函数来输出结果。
而被调用函数就是用来求平均值的。
利用循环先来求总和,再除去人数就可以求解。
主函数先来声明被调用函数。
这里是两次调用了average函数,但是他们需要处理的数组元素的个数是不同的。
这里面就用了score1和score2来区分。
我们需要始终记得,用数组名作函数实参时,
不是把数组元素的值传递给了形参,
而是把实参数组的首元素的地址传递给形参数组,
这样两个数组就共同占有同一段存储单元。
也正因此,形参数组中各元素的值如果发生了变化就会使实参数组元素的值同时发生变化。
下面来看一下延申的一个程序:
用选择法对数组中10个整数按由小到大的顺序排列。
这里面我们先定义一个长度为10的数组a,
选择法就是说先将10个数中最小的数与a[0]进行对换,
再将a[1]——a[9]中最小的数与a[1]对换,
每一轮的比较都会找出剩下的数中最小的那一个。
这样就会按照数组下标的顺序输出一列从小到大的数,也就完成了排序。
这个就是过程。
我们来看代码:
#include <stdio.h>
int main()
{
void sort(int array[],int n);
int a[10],i;
printf("enter array:\n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
sort(a,10);
printf("The sorted array:\n");
for(i=0;i<10;i++)
printf("%d ",a[i]);
printf("\n");
return 0;
}
void sort(int array[],int n)
{
int i,j,k,t;
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
if(array[j]<array[k])
k=j;
t=array[k];
array[k]=array[i];
array[i]=t;
}
}
我们来分析一下这个程序:
void sort(int array[],int n);
这个是定义被调用函数,数组元素定义为整型数据
int a[10],i;
printf("enter array:\n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
这里是定义一个大小为10的数组,并利用循环输入数组元素。
sort(a,10);
这里是调用函数
printf("The sorted array:\n");
for(i=0;i<10;i++)
printf("%d ",a[i]);
printf("\n");
return 0;
主函数的这一部分是输出调用函数后得到的结果。
int i,j,k,t;
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
if(array[j]<array[k])
k=j;
t=array[k];
array[k]=array[i];
array[i]=t;
被调用函数这里是经典的大小比较和排序,
利用了双重循环,来使得多个数组元素进行大小排序。
多维数组名作函数参数
多维数组名可以作为函数的形参和实参,
在被调用函数中对形参数组定义时可以指定每一维的大小,
也可以省略第一维的大小说明。
如:
int array[9][10]
int array[][10]
这两个是等价的。
可以省略第一维,不能省略第二维及其他高维。
对于二维数组,我们可以把第一维看成是行,第二维看成是列。
由此,二维数组是由若干个一维数组组成的。
在内存中,数组是按行存放的。
那么在用二维数组名来表示形参和实参时,一个程序中,形参和实参的长度是相同的,也就是列数相同。
那么我们在定义时就需要指明列数来规范数组,便于之间数据的传递,行数是不影响的。
也就是第一维的数据不相同也是可以进行数据传递的。
C语言的编译系统不会检查第一维的大小。
我们来看下面的一个程序:
有一个3X4矩阵,求所有元素中的最大值。
#include <stdio.h>
int main()
{
int max_value(int array[][4]);
int a[3][4]={{1,3,5,7},{2,4,6,8},{15,17,34,12}};
printf("Max value is %d\n",max_value(a));
return 0;
}
int max_value(int array[][4])
{
int i,j,max;
max=array[0][0];
for(i=0;i<3;i++)
for(j=0;j<4;j++)
if(array[i][j]>max)
max=array[i][j];
return(max);
}
这个就是用二维数组名来做函数参数。
结构还是很简单的。
主函数就是用来向二维数组中输入数据,
被调用函数就是利用双重循环来使二维数组中的所有元素进行比较,
求得最大值。