1. C语言
1.1 一般参数
#include <stdio.h>
void f(int i) // 置0
{
printf("f : %p %d\n", &i, i);
i = 0;
printf("f : %p %d\n", &i, i);
}
int main()
{
int a = 1;
printf("main: %p %d\n", &a, a);
f(a);
printf("main: %p %d\n", &a, a);
return 0;
}
运行结果
分析:因为实参地址(0022FEDC)和形参地址(0022FEC0)不同,所以实参p和形参i不是同一变量。修改i不会改变a。
1.2 指针参数
#include <stdio.h>
void f(int *i) // 修改指针
{
printf("f : %p %p %d\n", &i, i, *i);
int m = 0;
i = &m;
printf("f : %p %p %d\n", &i, i, *i);
}
int main()
{
int a = 1;
int *p = &a;
printf("main: %p %p %d\n", &p, p, *p);
f(p);
printf("main: %p %p %d\n", &p, p, *p);
return 0;
}
运行结果
分析:因为实参指针地址(0022FED8)和形参指针地址(0022FEC0)不同,实参p和形参i是两个不同的指针。因为p和i的值相等,都是0022FEDC,所以它们指向同一变量。修改i不会改变p。
#include <stdio.h>
void f(int *i) // 修改指针指向的值
{
printf("f : %p %p %d\n", &i, i, *i);
*i = 0;
printf("f : %p %p %d\n", &i, i, *i);
}
int main()
{
int a = 1;
int *p = &a;
printf("main: %p %p %d\n", &p, p, *p);
f(p);
printf("main: %p %p %d\n", &p, p, *p);
return 0;
}
运行结果
分析:因为实参指针地址(0022FED8)和形参指针地址(0022FEC0)不同,实参p和形参i是两个不同的指针。因为p和i的值相等,都是0022FEDC,所以它们指向同一变量。修改*i会改变*p。
1.3 数组参数
#include <stdio.h>
void f(int i[]) // 修改数组i
{
printf("f : %p %p %d\n", &i, i, *i);
int m = 0;
i = &m;
printf("f : %p %p %d\n", &i, i, *i);
}
int main()
{
int a[3] = {1, 2, 3};
printf("main: %p %p %d\n", &a, a, *a);
f(a);
printf("main: %p %p %d\n", &a, a, *a);
return 0;
}
运行结果
#include <stdio.h>
void f(int i[]) // 修改数组元素i[0]
{
printf("f : %p %p %d\n", &i, i, *i);
i[0] = 0;
printf("f : %p %p %d\n", &i, i, *i);
}
int main()
{
int a[3] = {1, 2, 3};
printf("main: %p %p %d\n", &a, a, *a);
f(a);
printf("main: %p %p %d\n", &a, a, *a);
return 0;
}
运行结果
分析:传递数组,实际是传递数组起始元素的位置或地址。实参a与形参i是两个不同的数组名,但它们的值都是0022FED4,指向同一变量。修改i不会改变a,修改i[0]才会改变a[0]。
1.4 总结
- 在C语言中,所有函数参数都是值传递,地址也是一种值。函数调用时,实参的值被赋给形参,修改形参不会改变实参。
- 传递指针实际是传递变量的地址。形参和实参是不同指针,但指向同一变量。修改形参不会改变实参,修改形参指向的变量会改变实参指向的对象。
- 传递数组实际是传递数组起始元素的地址。与指针类似,修改形参不会改变实参,修改形参的数组元素会改变实参的数组元素。
2. C++语言
2.1 一般参数
#include "iostream"
using namespace std;
void f(int i) // 置0
{
cout << "f : " << &i << " " << i << endl;
i = 0;
cout << "f : " << &i << " " << i << endl;
}
int main()
{
int a = 1;
cout << "main: " << &a << " " << a << endl;
f(a);
cout << "main: " << &a << " " << a << endl;
return 0;
}
运行结果
分析:&a是0x22fecc,&i是0x22feb0,a和i是不同变量,修改a不会改变i。
2.2 指针参数
#include "iostream"
using namespace std;
void f(int *i) // 修改指针
{
cout << "f : " << &i << " " << i << " " << *i << endl;
int m = 0;
i = &m;
cout << "f : " << &i << " " << i << " " << *i << endl;
}
int main()
{
int a = 1;
int *p = &a;
cout << "main: " << &p << " " << p << " " << *p << endl;
f(p);
cout << "main: " << &p << " " << p << " " << *p << endl;
return 0;
}
运行结果
#include "iostream"
using namespace std;
void f(int *i) // 修改指针指向的变量
{
cout << "f : " << &i << " " << i << " " << *i << endl;
i[0] = 0;
cout << "f : " << &i << " " << i << " " << *i << endl;
}
int main()
{
int a = 1;
int *p = &a;
cout << "main: " << &p << " " << p << " " << *p << endl;
f(p);
cout << "main: " << &p << " " << p << " " << *p << endl;
return 0;
}
运行结果
分析:传递指针时,会将实参拷贝给形参。形参i与实参p是两个不同的指针,它们都指向同一变量a。修改i不会改变p,修改*i会改变*p。
2.3 数组参数
#include "iostream"
using namespace std;
void f(int i[]) // 修改数组
{
cout << "f : " << &i << " " << i << " " << *i << endl;
int m[3] = {0, 0, 0};
i = m;
cout << "f : " << &i << " " << i << " " << *i << endl;
}
int main()
{
int a[3] = {1, 2, 3};
cout << "main: " << &a << " " << a << " " << *a << endl;
f(a);
cout << "main: " << &a << " " << a << " " << *a << endl;
return 0;
}
运行结果
#include "iostream"
using namespace std;
void f(int i[]) // 修改数组元素
{
cout << "f : " << &i << " " << i << " " << *i << endl;
i[0] = 0;
cout << "f : " << &i << " " << i << " " << *i << endl;
}
int main()
{
int a[3] = {1, 2, 3};
cout << "main: " << &a << " " << a << " " << *a << endl;
f(a);
cout << "main: " << &a << " " << a << " " << *a << endl;
return 0;
}
运行结果
分析:传递数组时,实际上传递的是指向数组首元素的指针。形参i与实参a是两个不同的指针,它们都指向同一变量。修改i不会改变a,修改i[0]会改变a[0]。
2.4 引用参数
#include "iostream"
using namespace std;
void f(int &i) // 修改i
{
cout << "f : " << &i << " " << i << endl;
i = 0;
cout << "f : " << &i << " " << i << endl;
}
int main()
{
int a = 1;
cout << "main: " << &a << " " << a << endl;
f(a);
cout << "main: " << &a << " " << a << endl;
return 0;
}
运行结果
分析:形参i是引用类型,i引用a,即i是a的别名。对i的操作实际上是对a进行操作,故修改i会改变a。
注意:C语言中,形参不能是引用类型。
#include <stdio.h>
void f(int &i)
{
printf("f : %p %d\n", &i, i);
i = 0;
printf("f : %p %d\n", &i, i);
}
int main()
{
int a = 1;
printf("main: %p %d\n", &a, a);
f(a);
printf("main: %p %d\n", &a, a);
return 0;
}
编译错误
运行错误
2.5 总结
- 在C++中,参数传递分为值传递和引用传递两种。程序调用函数时会创建形参,并用实参对形参初始化。
- 传递数组实际上是传递指向数组首元素的指针。数组传递和指针传递都算是值传递。
- C++中形参可以是引用类型,C中不可以。