最近开始复(yu)习(xi)C语言,看到参数传递这里,又遇到了以前一直没有搞清楚的一个问题,我相信这个问题大家许多初学者也会遇到过,就是C语言函数的参数传递方式。
C语言中参数的传递有两种方式:
1)值传递
2)地址传递
3)数组作为函数参数
这里用两个例子来说明这两种方式的区别。
- 值传递
int main(){
int a=3;
int b=4;
printf("初始值a=%d,b=%d\n",a,b);
exchange(a,b);
printf("运行后a=%d,b=%d",a,b);
return 0;
}
void exchange(int a ,int b){
int temp;
temp=a;
a=b;
b=temp;
}
运行结果:
- 地址传递
int main()
{
int i,j,k;
int data[100];
int length=3;
int a=3;
int b=4;
printf("初始值a=%d,b=%d\n",a,b);
exchange(&a,&b);
printf("运行后a=%d,b=%d",a,b);
}
void exchange(int *a ,int *b){
int temp;
temp =*a;
*a=*b;
*b=temp;
}
运行结果:
why?
老生常谈的问题了,我们预期的是ab的值会交换,但是并没有达到预期的效果,因为这个函数使用的是值传递。
我个人是这样的理解的
main函数中声明的ab两个变量,看作是计算机中的两个盘子A,B。A盘子中放的是“3”,B盘子中放的是“4”。
值传递的方式,只是把两个盘子中的东西作为参数传入,起到的是一种模板作用,函数收到这两个参数之后,会找到另外两个跟“3”“4”一样的东西,对这两个东西进行操作。而并不会改变main中原来两个盘子的值。而地址传递,就是把A,B这个两个盘子作为参数传过去了,进行的操作会影响到这个盘子里的东西。
换言之,我们去饭店点菜,有时大厅中能看到保鲜膜裹着的样品菜,我们指着桌上盛放“鱼香肉丝”的盘子告诉服务员我们要这个菜,厨师会另取相同的食材做出我们点的“鱼香肉丝”,而原本放在大厅里的样菜并没有动。----这是值传递。
相反,我们跟服务员说,我们就要这个盘子里的菜,这样厨师就直接烹饪了我们指定的盘子里的菜。----这是地址传递。
另外还看到一种引用传递,是c++语言中参数的传递方式,声明格式如下
void exchange(int &a,int &b){
/*操作*/
}
另外需要注意的是,C语言中使用地址传参,声明的格式是void function(int *a)
而调用的格式是:function(&a)
因为传递的参数是地址,所以在调用时候要有“&”取地址符号!
- 数组作为函数参数
1)数组元素作为函数参数,函数的声明没有什么差别,还是分为上述的两种方式:void function(int a);//值传递
或者是void function(int *a);//地址传递
,调用函数时分别采用function(a[2]);
或者function(&a[2]);
这种情况下,存在值传递与地址传递的不同,参考上述。
2)数组名作为参数传递:
例如function(int a[])
调用函数:function(a);//这里a是一个数组名字
用数组名做函数实参时,不是把数组元素的值传给形参,而是把实参数组的首元素的地址传递给形式参数,也就是说形参数组发生改变,会使实参数组发生同样的变化。换言之,函数进行的操作就是直接发生在传递进来的数组上的。
下面举一个例子,对数组a中的数字进行排序
#include stdio.h
int main()
{
int i;
int n=6;
int a[6]={7,5,3,4,12,54};
for(i=0;i<n;i++) printf("%d ",a[i]);
printf("\n排序之后\n");
Sort(a,n);
for(i=0;i<n;i++) printf("%d ",a[i]);
return 0;
}
void Sort(int a[],int n){
int i,j;
int tmp=0;
for(i=0;i<n;i++){
for(j=0;j<n-1-i;j++){
if(a[j]>a[j+1]){
tmp=a[j];
a[j]=a[j+1];
a[j+1]=tmp;
}
}
}
}
运行结果:
可以看出,函数名作为参数时,所做的操作会直接影响原来的数组。