C/C++ 读懂函数的形参和实参,一篇文章足够了
案例1:形参为非指针变量
int _tmain(int argc, _TCHAR* argv[])
{
unsigned char a_param = 1;
printf("a_param 的地址为 = %%p,a_param 的值 = %%d
", &a_param, a_param);
FunParam(a_param);
printf("执行后
");
printf("a_param 的地址为 = %%p,a_param 的值 = %%d
", &a_param, a_param);
return 0;
}
/// unsigned char c_param = a_param;
void FunParam(unsigned char c_param)
{
printf("c_param 的地址为 = %%p, c_param 的值为 = %%d
", &c_param, c_param);
c_param = 2;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
执行
这里看到,形参c_param 和实参 a_param 在不同的地址上,但值相等。函数调用时,形参和实参的关系,可以这么表示
unsigned char c_param = a_param;
定义了一个c_param,将a_param 赋值给它。在这种情况下,形参和实参没有任何关系,因为它们在不同的地址上,改变形参不会影响实参。
案例2:形参为指针变量
int _tmain(int argc, _TCHAR* argv[])
{
unsigned char debug_data = 2;
unsigned char *a_param = &debug_data;
printf("a_param 的地址为 = %%p,a_param 的值 = %%d
", a_param, *a_param);
FunParam(a_param);
printf("执行后,a_param 的地址为 = %%p, a_param 的值为 = %%d
", a_param, *a_param);
return 0;
}
/// unsigned char *c_param = a_param;
void FunParam(unsigned char *c_param)
{
printf("c_param 的地址为 = %%p, c_param 的值为 = %%d
", c_param, *c_param);
*c_param = 3;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
执行
这里我们定义了一个FunParam 函数,形参时一个指针。同样的,我们用上面那个公式
unsigned char *c_param = a_param
函数调用时,定义了一个形参c_param,这个指针指向了a_param 这个指针所指向的内存地址(0x010FFE93),此时两个指针同时指向了同一块内存地址,因此当一个指针操作了这块内存地址,改变了值,另一个指针去访问这块内存时,值自然就变了。因此这种情况下,形参可以改变实参
案例3: 形参为指针的指针
int _tmain(int argc, _TCHAR* argv[])
{
unsigned char debug_data = 2;
unsigned char *a_param = &debug_data;
printf("a_param 的地址为 = %%p, a_param指向的地址为 = %%p, a_param的值 = %%d
", &a_param, a_param, *a_param);
FunParam(&a_param);
printf(" 执行后
");
printf("a_param 的地址为 = %%p, a_param指向的地址为 = %%p, a_param的值 = %%d
", &a_param, a_param, *a_param);
return 0;
}
/// unsigned char **c_param = &a_param;
void FunParam(unsigned char **c_param)
{
printf("c_param 的地址为 = %%p, c_param 指向的地址为 = %%p,c_param 的值为 = %%d
", c_param, *c_param, **c_param);
*c_param = (unsigned char*)malloc(1);
if (c_param != NULL)
{
*(*c_param) = 3;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
执行
我们可以看到,执行后,实参指针指向的内存地址变了。同样套用公式
unsigned char **c_param = &a_param
调用函数时,定义了一个二级指针,指向了实参指针的地址,函数内,通过动态内存分配,二级指针操作实参指针的地址,将实参指针重新指向一块内存,并重新赋值。案例2只能改变指针指向的内存地址上的值,无法改变指针的指向;但是这里,我们不仅可以改变指针指向的内存的值,也可以改变指针的指向。我们往往通过这种方式,来初始化一个空指针。初始后,若要释放内存,则可使用方案2的处理,重新定义一个指针指向那块动态内存,然后释放
案例4:引用
int _tmain(int argc, _TCHAR* argv[])
{
unsigned char a_param = 1;
printf("a_param 的地址为 = %%p,a_param 的值 = %%d
", &a_param, a_param);
FunParam(a_param);
printf("执行后
");
printf("a_param 的地址为 = %%p,a_param 的值 = %%d
", &a_param, a_param);
return 0;
}
/// unsigned char &c_param = a_param;
void FunParam(unsigned char &c_param)
{
printf("c_param 的地址为 = %%p, c_param 的值为 = %%d
", &c_param, c_param);
c_param = 2;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
执行后
依旧套用公式
unsigned char &c_param = a_param
引用的本质就是取一个别名,本体还是一样的。这里我们看到行参和实参的地址相同,因此改变形参等同于改变实参