假设你要编写一个对数组进行操作的函数,目的就是要此函数返回数组内所有元素的和,并假设marbles为这个int数组的名称。应该如何调用这个函数?一种合乎情理的猜测如下:
total=sum(marbles);//可能的函数调用
那么原型是什么样的?数组名同时代表数组首元素的地址,因此实际参数marbles是一个int的地址,应把它赋给一个类型为指向int的指针的形式参量:
int sum(int * ar);//相应的原型
函数sum()从该参数可以得到什么信息?它得到数组首元素的地址,而且知道可以从此地址找到一个int。请注意它无从知道数组中元素的数量。于是在函数的定义中有两种选择,一个是在函数代码中协商固定的数组大小,如下:
int sum(int * ar,int n) //更通用的方法
{
int i;
int total=0;
for(i=0;i
这里的第一参数把数组地址和数组类型的信息传递给函数。第二个参数把数组中的元素个数传递给函数。
此外,关于函数常量有一件需要说明的事情:在函数原型或函数定义头的场合中,可以用,int * ar 代替int ar[]:
int sum(int ar[],int n);
无论在任何情况下,形式int *ar都表示ar是指向int的指针。形式int ar[ ]也可以表示ar是指向int的指针,但只是在声明形式参量时才可以这样使用。使用第二种形式可以提醒我们ar不仅指向一个int数值,而且它指向的这个int是一个数组的元素。
声明数组参量
由于数组名就是数组首元素的地址,所以如果实际参数是一个数组名,那么形式参量必须是与之相匹配的指针。在这种场合中,C对于int ar[]和int * ar作出同样解释,即ar是指向int的指针。由于原型允许省略名称,因此下面的四种原型都是等价的。
int sum(int *ar,int n);
int sum(int *,int );
int sum(int ar[],int n);
int sum(int [],int);
定义函数时,名称是不可以省略对的,因此,在定义时下面两种形式是等价的:
int sum(int *ar ,int n)
{
//代码
}
int sum(int ar[],int n)
{
//代码
}
下面是一个对数组所有元素求和的sum()程序。为了说明关于数组参数的一个有趣的事实,此程序同时打印出原数组的大小和代表数组的函数参量的大小。
//sum_arr.c --对一个数组的所有元素求和
#include
#define SIZE 10
int sum(int ar[], int n);
int main(void)
{
int marbles[SIZE] = { 20,10,5,39,4,16,119,26,31,20 };
long answer;
answer = sum(marbles, SIZE);
printf("The total number of marbles is %ld.\n", answer);
printf("The size of marbles is %zd bytes.\n", sizeof marbles);
return 0;
}
int sum(int ar[], int n) //数组的大小是多少?
{
int i;
int total = 0;
for (i = 0; i < n; i++)
{
total += ar[i];
}
printf("The size of ar is %zd bytes.\n", sizeof ar);
return total;
}
输出结果为:
The size of ar is 4 bytes.
The total number of marbles is 290.
The size of marbles is 40 bytes.
请注意marbles的大小为40字节。的确如此,因为marbles包含10个int类型的数,每个数占4个字节,因此总共占用40个字节。但是ar的大小只有4个字节。这是因为ar本身并不是一个数组,它是一个指向marbles的首元素的指针。对于采用4字节地址的计算机系统,指针的大小为4个字节。总之,在上面的程序中,marbles是一个数组,而ar是一个指向marbles首元素的指针。