形不改实
形参的改变一般不会影响实参的改变。
传值
void fun1(int a,int b)
{
int t;
t = a;
a = b;
b = t;
}
int main()
{
int a=4,b=3;
fun1(a,b);
printf("%d %d\n",a,b);
return 0;
}
输出:4 3
由上面的例子可以看出,实参的改变没有影响到实参的改变。
原因是形参a,b的作用域只在fun1函数里,函数结束形参也就被释放了。而且调用函数fun1时,实参传递给形参时,不是用实参替换形参,而是用实参给形参赋值!
相当于void fun1(int a=a,int b=b);第一个a或b为形参,第二个a或b为实参,在fun1里,a和b的交换是形参之间的交换,并没有影响实参。
传址
void fun2(int *a,int *b)
{
int t; //注意这里不能定义为int *t;//野指针
t = *a;
*a = *b;
*b = t;
}
int main()
{
int a=4,b=3;
fun2(&a,&b);
printf("%d %d\n",a,b);
return 0;
}
输出:3 4
原因:将实参的地址赋值给形参,相当于void fun2(int *a=&a,int *b=&b);即形参指针a指向了实参a的地址,形参指针b指向了实参b的地址。*a 和 *b为指向的地址的内容。所以函数调用完会改变实参,将实参的值进行交换。
是不是传址就会影响到实参呢?
传址影响到实参的本质是将地址的内容进行改变,若只改变地址也不会影响到形参。
void fun3(int *a,int *b)
{
int *t; //这里定义了一个野指针,只要没有对它指向的地址的内容进行操作就不会出错,我们可以改变它的指向。
t = a;//将指针t指向了指针a所指向的地址
a = b;
b = t;
}
int main()
{
int a=4,b=3;
fun2(&a,&b);
printf("%d %d\n",a,b);
return 0;
}
输出:4 3
原因:这里只是改变了指针的指向,并没有对指针指向的地址内的内容进行操作。fun3函数的作用是指针a指向了实参b的地址,指针b指向了实参a的地址,但指针a,b的生存期只在fun3函数里,函数调用完毕后,指针a,b就不存在了。
若要改变变量的地址或一级指针,则形参要定义为二级指针。
二级指针可以理解为地址的地址
void fun4(int **c,int **d)
{
int *t;
t = *c;
*c = *d;
*d = t;
}
int main()
{
int a=4,b=3;
int *p=&a,*q=&b,*m=&a,*n=&b;
fun4(&p,&q);
printf("%d %d %d %d\n",p,q,m,n);
return 0;
}
输出:6422024 6422028 6422028 6422024
函数有返回值
int fun4(int m)
{
m=4;
return m;
}
int main()
{
int a=3;
fun4(a);
b=fun4(a);
printf("a=%d ,b=%d\n",a,b);
return 0;
}
输出:a=3,b=4
当调用函数时,函数有返回值,但没有将函数赋值给实参,即函数返回值赋值给实参,则实参不会改变。虽然形参的作用域只在函数内,但函数的返回值会暂存在寄存器中,当函数赋值给实参时,会从寄存器中将返回值赋值实参。