C语言函数参数传递
1.值传递
void swap(int x,int y) { int temp = x; x = y; y = temp; } void main() { int a = 10, b = 20; swap(a, b); }
执行后,并不会交换。
2.引用传递
void swap(int &x,int &y) { int temp = x; x = y; y = temp; } void main() { int a = 10, b = 20; swap(a, b); printf("a=%d\nb=%d\n", a, b); }
执行后,发生交换。
3.指针传递
void swap(int *x,int *y) { int temp = *x; *x = *y; *y = temp; } void main() { int a = 10, b = 20; swap(&a, &b); printf("a=%d\nb=%d\n", a, b); }
执行后,发生交换。
4.数组做参数,传的到底是什么?
参数传递只有上面三种,但是如果加上数组,就会产生几种新形式。
首先,明确数组型变量名本身只是该数组所占存储空间的首地址:
int a[3] = { 1, 2, 3 }; int *p = a; //等价于下行 //int *p = &a[0]; printf("%d", *p);
》》》典型的数组做参数
void fun(char s[]){ for (int i = 0; s[i] != '\0'; i++) printf("%c", s[i]); } void main() { char str[] = "Hello World!"; fun(str); }
函数调用时,这里系统不会为形参分配数组存储空间,而是仅仅分配一个存放数组地址(第一个元素地址)的存储空间,此后,将实参数组的首地址传递给形参变量。其实本质与下相同,只不过还是数组形式的(数组名代替指针)。
》》》既然数组型变量名本身只是该数组所占存储空间的首地址,我们当然可以用指针做形参来接收数组实参
void fun(char *p){ while (*p) { printf("%c", *p); p++; } } void main() { char str[] = "Hello World!"; fun(str); }
不过问题是如果这样,无法把握数组结束(除非知道数组长度)。而对于字符数组(上例),由于字符串末尾有结束标志'\0'(ascii码正好是0),所以就很容易利用指针来判断字符串是否结束。
数组作为函数参数
3.1数组元素作为函数参数
数组元素又称为下标变量,它具有普通变量的一切性质,因此数组元素作为函数的实参进行数据传递是与普通变量没有任何区别,也是值传递
-
int swap(int a,int b)
-
{
-
int temp;
-
temp=a;
-
a=b;
-
b=temp;
-
return 0;
-
}
-
int main (void){
-
int a[]={3,4};
-
swap(a[0],b[0]);
-
}
同样是值传递并不会改变a[0]的值。
3.2一维数组名作为函数参数
数组名是一个地址,是数组的首地址,因此用数组名作为函数的参数进行数据传递时,执行的是地址传递方式。所谓地址传递,顾名思义实参传递的不是数据本身,而是数据存在的地址。函数调用时,把数组名即数组的首地址作为实参传递给形参(必须是可接受地址的数组名或者指针变量),形参数组名取得首地址后就有了实在的数组,这时实质上实参和形参是同一个数组,指向同一段存储空间,实参的改变就是对形参的改变,所以传址方式可看成是数据进行了“双向传递”。
3.3数组指针,即数组元素的地址作为函数参数
由于数组元素的地址的本质仍然为地址,所以属于地址传递方式。
-
int swap(int *a,int *b)
-
{
-
int temp;
-
temp=*a;
-
*a=*b;
-
*b=temp;
-
return 0;
-
}
-
int main (void){
-
int arr[] = {1,2};
-
int *a = &arr[0];
-
int *b = &arr[1];
-
swap(a,b);
-
}
重点:
- 数组元素(下标变量)作为函数的参数进行的数据传递是值传递方式,数组名(数组首地址)、数组元素的地址(&arr[0])作为函数参数进行的数据传递是地址传递方式。
- 实参为数组名是,形参接收时可以有三种形式:带下标的数组名(arr[0])。不带下标的数组名(arr)、可接收地址值的指针变量名(*a)。由于是参数组和形参数组都指向同一段内存单元,故它们操作的是同一批数据,所以形参的改变就是改变了实参中的数据。