7、数组做为参数传递给函数
可以将数组做为传递给函数,比如下面的代码就是将传入输入的每个元素乘以2:
void makeDoule(int arr[],int len)
{
int i=0;
for(i=0;i<len;i++)
{
arr[i]= arr[i]*2;
}
}
int main(int argc, char *argv[])
{
int a1[5]={3,5,6,8,2};
int i = 0;
int len=sizeof(a1)/sizeof(int);
makeDoule(a1,len);
for(i=0;i<len;i++)
{
printf("%d ",a1[i]);
}
}
运行结果:
6 10 12 16 4传递给makeDoule函数的是a1,我们知道,一个数组的名字其实就是指向数组首元素的地址。所以makeDoule函数得到的arr就是数组a1的指针,那么在函数内部对arr进行操作的话就会改变a1数组。
所以makeDoule函数也可以写成下面的样子,这两个函数是等价的:
void makeDoule(int* arr,int len)
{
int i=0;
for(i=0;i<len;i++)
{
arr[i]= arr[i]*2;
}
}
当然写成下面的形式更符合指针的使用习惯,因此推荐这种用法:
void makeDoule(int* arr)
{
int i=0;
for(i=0;i<5;i++)
{
//arr+i指向的值设置为arr+i指向的值的二倍。
*(arr+i)= *(arr+i)*2;
}
}
有的同学可能会问,为什么makeDoule函数还需要传递数组的长度len呢?makeDoule函数这样写不就行了吗?
void makeDoule(int* arr)
{
int i=0;
for(i=0;i<5;i++)
{
arr[i]= arr[i]*2;
}
}
这样写在这个函数中是没有问题的。但是这个makeDoule函数不一定为只为a1服务,函数的最重要的特征是可以复用,也就是可以被其他地方调用,如果我们想用makeDoule函数为另外一个长度为20的数组进行“每个元素乘以2”的操作,那么将数组长度5写死在函数中就会有问题了。
那么为什么不在函数内部计算数组的长度呢?省得还传递一个len参数
void makeDoule(int arr[])
{
int i=0;
int len = sizeof(arr)/sizeof(int);
for(i=0;i<len;i++)
{
arr[i]= arr[i]*2;
}
}
int main(int argc, char *argv[])
{
int a1[5]={3,5,6,8,2};
int i = 0;
int len=sizeof(a1)/sizeof(int);
makeDoule(a1);
for(i=0;i<len;i++)
{
printf("%d ",a1[i]);
}
}
运行以后程序竟然输出了:6 5 6 8 2
只有第一个元素被“乘以2”。为什么呢?
运行下面的程序试一试:
void test(int arr[])
{
printf("%d/n",sizeof(arr)/sizeof(int));
}
int main(int argc, char *argv[])
{
int a1[5]={3,5,6,8,2};
printf("%d/n",sizeof(a1)/sizeof(int));
test(a1);
}
运行结果竟然是:
5
1为什么在main函数中计算数组的大小是5,在test函数中计算数组arr的大小就变成了1了呢?在C语言中可以通过sizeof的方式取得一个数组的尺寸,这是我们已经知道的。但是一旦把这个数组传递给函数的时候,到了函数内部使用的就是指向这个数组的指针了,虽然在test函数中arr声明的是数组,但是这里的arr只是一个指针而已了,arr本质上只是一个int类型的指针,而int类型的指针的大小是4,所以sizeof(arr)/sizeof(int)的结果就是1。这点是经常容易犯错的,需要特别注意。
int main(int argc, char *argv[])
{
int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};
printf("%d/n",*(*(a+1)+2));
printf("%d/n",*(a[1]+2));
}
程序输出如下:
6
6两个表达式都输出a[1][2]的值。*(a+1)则表示二维数组a的第1行,也就是等价于a[1]。a[1]、*(a+1)都表示数组的第1行。所以*(a[1]+2))和*(*(a+1)+2)都表示数组的第1行的第2个元素的值。
有的同学会问了,既然“*(a+1)”和“a+1”是等价的,为什么“printf("%d/n",*((a+1)+2)))”输出结果是错误的呢?
编译器在编译“*((a+1)+2)))”的时候会把“(a+1)+2”优化成“a+3”,因此“*((a+1)+2)))”就变成了“*(a+3)”,也就是a数组第3个一维数组的首地址,显然这个只是一个地址,并不是我们想像中的a[1][2]的值,所以输出了一个非常大的数。为了避免编译器的这种误解,建议大家表示“二维数组a的第1行”的时候用a[1]或者*(a+1),而尽量不要用(a+1)因为很容易出错。