目录
对带有参数的函数进行调用时,存在着如何将实参传递给行参的问题。根据实参传递给行参值的不同,通常有值传递方式和地址传递方式两种。
一、运用值传递方式
所谓值传递方式是:函数调用时,为行参分配内存单元,并将实参的值复制到行参中;调用结束,行参所占内存单元被释放,实参的内存单元仍保留原值。
其特点是:行参和实参占用不同的内存单元,函数中对行参值的改变不会影响实参的值。这就是函数参数的值单向传递规则。
形参:形参是功能函数里的变量,只有被调用的时候才分配内存单元,调用结束后立即释放内存,只在函数内部有效。
实参:也就是实际要拷贝给形参的参数,可以是常量,变量,等,但不管是什么类型,必须具有确定的值,注意并保证实参的个数,类型应与形参一一对应。
1、函数的值传递方式举例
#include<stdio.h>
void swap(int a,int b); //函数原型声明
int main()
{
int x=7,y=11;
printf("before swapped:");
printf("x=%d,y=%d\n",x,y);
swap(x,y) //函数调用(x、y为实参,值传递方式)
printf("after wapped:");
printf("x=%d,y=%d\n",x,y);
return 0;
}
void swap(int a,int b) //函数定义(a,b为行参)
{
int temp;
temp=a;
a=b;
b=temp;
}
运行结果:
before swapped:x=7,y=11
after wapped:x=7,y=11
程序解释:
该程序首先在main函数中定义了两个整型变量x和y,其初始值分别为7和11,然后调用swap自定义函数试图交换x,y的值,可结果是,调用函数swap以后,x和y的值并没有交换,x仍然是7,y仍然是11。为什么会出现这种情况呢?这是因为实参x和y对应的内存单元与形参a和b所对应的内存单元是各不相同的,在函数调用时,只是将x的值7传递给形参a,y的值11传递给形参b,在swap函数体内只是将a和b的值交换了,即a的值变为11,b的值变为7,当函数返回时,a和b的内存单元就释放了,变量x和y所对应的内存单元并没有任何的改变。
二、运用地址传递方式
所谓地址传递方式是:函数调用时,将实参数据的存储地址作为参数传递给形参。
其特点是:形参与实参占用同样的内存单元,函数中对形参值的改变也会改变实参的值。因此函数参数的地址传递方式可实现调用函数与被调函数之间的双向数据传递。注意,实参和形参必须是地址常量或地址变量。比较典型的地址传递方式就是用数组名作为函数的参数,在用数组名作函数参数时,不是进行值的传送,即不是把实参数组的每一个元素的值都赋予形参数组的各个元素。因为实际上形参数组并不存在,编译系统不为形参数组分配内存。那么,数据的传送是如何实现的呢?数组名就是数组的首地址。因此在数组名作函数参数时所进行的传送只是地址的传送,也就是说,把实参数组的首地址赋予形参数组名。形参数组名取得该首地址之后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组,共同拥有同一段内存空间。
1、函数的地址传递方式举例
#include<stdio.h>
void mergestr(char s1[], char s2[], char s3[]); //函数原型声明
int main()
{
char str1[]={"Hello "};
char str2[]={"china!"};
char str3[40];
mergestr(str1, str2,str3); //函数调用(str1、str2、str3为实参,地址传递式)
printf( "%s\n", str3);
return 0;
}
void mergestr(char s1[], char s2[], char s3[])//函数定义(s1、s2、s3为形参)
{
int i, j;
for( i=0;s1 [i]!='\0';i++) //将s1复制到s3中
s3[i] =s1[i] ;
for(j=0;s2[j]!='\0';j++) //将s2复制到s3的后边
s3[i+j]=s2[j];
s3[i+j]='\0'; //置字符串结束标志
}
运行结果:
Hello china!
程序解释:
在main函数中定义了三个字符数组str1、str2、str3,通过调用mergestr函数将strl字符串与str2字符串相连接后形成一个新的字符串放入str3中。然后输出连接后的字符串。
mergestr函数带有三个形参,分别是数组名s1、s2、s3。main在调用该函数时是将三个字符数组名str1、str2、str3(即三个数组所对应内存单元的首地址)赋值给三个形参s1、s2、s3,这样一来,s1、s2、s3所对应的数组其实就分别是str1、str2、str3了。在函数中具体实现连接的方法是首先将s1字符串(其实就是strl)逐个字符地复制到s3(其实就是str3)中,然后再将s2字符串(其实就是str2)逐个字符地复制到s3的末尾。复制完后,最后要在s3的末尾添加字符串结束标志'\0'。
用数组名作为函数参数时还应注意以下几点:形参数组和实参数组的类型必须一致,否则将引起错误。
形参数组和实参数组的长度可以不相同,因为在调用时,只传送首地址而不检查参数组的长度。
当形参数组是一维数组时,既可指定形参数组的长度,也可以省略,但[]不可省略。
多维数组也可以作为函数的参数。在函数定义时对形参数组可以指定每一维的长度,也可省略第一维的长度,但其他维的长度不可省略。
除了用数组名作为函数参数来实现参数的地址传递以外,其实还有一种应用更广泛的地址传递方法,那就是用指针变量来作为函数的形参。