写这一篇博客的主要目的,在于整理回顾C语言中关于参数传递的内容。大家最早接触参数传递,肯定都是在学习子函数的时候,比如 下面这一段很简单的代码:
#include<stdio.h>
void main()
{
int max(int i,int j);
int a = max(1,5);
printf("a = %d\n",a);
system("pause");
}
int max(int i, int j)
{
return (i > j) ? i : j;
}
在main函数中调用max子函数,同时传递进去两个值(1,5),最后输出结果 a=5。这种方式就是最简单的传递值。
一、传递值
后来,我们发现有的时候使用这种方法不能达到我们想要的结果。比如下面这段代码:
#include<stdio.h>
void main()
{
void swap_1(int a,int b);
int a, b;
a = 1;
b = 3;
printf("Before changing, the result:\na = %d\nb = %d\n\n", a, b);
swap_1(a,b);
printf("When transmit the value, the result:\na = %d\nb = %d\n\n", a, b);
system("pause");
}
void swap_1(int a, int b)
{
int temp;
temp = a;
a = b;
b = temp;
}
同样,我们在main函数中传入了a和b的值,本来以为能利用swap_1函数,将a和b中的值互换,但是最后发现输出结果依旧是a=1 b = 3。这里就需要把实参和形参区别开来,并且知道参数传递中,传值是单向传递的。
一方面,虽然我们把swap函数的形参取名a和b,但是这两个和main函数里定义的a和b完全是不相干的两码事。实参a和b在将自己的数值交给子函数后,就不会管子函数中的发生的事了。而swap_1函数中,a和b的值不管怎么变换,都不会影响实参。
另一方面,在我们平时写代码的时候,应该尽量避免形参命名与实参相同,避免不必要的误会。
二、传递地址值
接着,我们学习了指针,知道第二种传递方式叫做传递地址值。并且可以很好的解决上述我们想实现的swap效果:
#include<stdio.h>
void main()
{
void swap_2(int *p1,int *p2);
int a, b;
a = 1;
b = 3;
printf("Before changing, the result:\na = %d\nb = %d\n\n", a, b);
swap_2(&a, &b);
printf("When transmit the value of address, the result:\na = %d\nb = %d\n", a, b);
system("pause");
}
void swap_2(int *p1, int *p2)
{
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
这里我们传递的是int型实参变量a和b所在内存单元的地址值,就是说告诉了子函数swap_2:把这两个内存单元里的内容进行一个交换。这样的话,子函数根据地址值找到对应的内存单元,并将两个内存单元中的数据内容进行互换。从而达到了预期效果。
三、传递地址
最后,我们在接触数组和指针的配合使用的时候,我们发现可以直接将数组名作为实参传递给子函数,并且对应的子函数的形参也是一个数组。称之为:传递地址。比如下面这段代码:
#include<stdio.h>
void main()
{
void print(int array[5]);
int a[5] = {1,2,3,4,5};
print(a);
printf("a[0] = %d\n",a[0]); //检验print函数是否能够修改原数组中的内容
system("pause");
}
void print(int array[5])
{
int i;
for (i = 0; i < 5; i++)
{
array[i] ++;
printf("%d \n",array[i]);
}
}
这里面传递了地址a,也就是数组a的在内存中的开始地址。这样形参同样就直接可以操纵数组所在的那一片内存区域了。并且,我们通过检验,发现最后一行输出:a[0] = 2 ,证明在传递地址时,子函数确实能够操作甚至修改原数组内容。
四、总结
以上的三个说法其实只是便于理解,正式的问法及答案应该如下:
question: 数组可以作为函数的参数使用,那么数组作函数参数有哪三种形式?
answer:1.数组元素作为实参使用(传递值);
2.形参是指针,实参是数组(传递地址值);
3.形参和实参都是数组(传递地址)。
如果理解了我举的三个例子,再来类比它们分别对应于数组中的用法,其实也能很快理解并加以记忆。下面还是给出三种方式在数组中的具体应用的代码:
#include<stdio.h>
void main()
{
void print_1(int value); //transmit the value
void print_2(int *p); //transmit the value of address
void print_3(int array[5]); //transmit the address
int a[5] = {1,2,3,4,5};
print_1(a[0]);
print_2(a);
print_3(a);
system("pause");
}
void print_1(int value) //transmit the value
{
printf("When transmit the value, a[0] = %d\n",value);
}
void print_2(int *p) //transmit the value of address
{
int i;
printf("When transmit the value of address, the result:\n");
for (i = 0; i < 5; i++)
printf("%d\n",*(p+i));
}
void print_3(int array[5]) //transmit the address
{
int i;
printf("When transmit the address, the result:\n");
for (i = 0; i < 5; i++)
printf("%d \n",array[i]);
}
就是这个样子,希望能给大家帮助,谢谢。