前言
本文介绍C函数传参的问题
一、传值方式调用函数
传值实际就是把变量的值拷贝到函数的形式参数,所以在函数体里修改了形参的值不会改变形参。代码如下:
#include <stdio.h>
#include <stdlib.h>
void Swap(int d1, int d2)
{
int temp;
temp = d1;
d1 = d2;
d2 = temp;
}
int main() {
int d1 = 10;
int d2 = 20;
printf("交换前:%d, %d\n", d1, d2); // 10, 20
Swap(d1, d2);
printf("交换后:%d, %d\n", d1, d2); // 10, 20
}
上面代码执行后,main函数里面的 d1和d2 的值并没有发交换。函数是局部变量的传递,是发生在栈中,main函数中的d1和d2b被复制到函数的形参中,函数里面修改形参值不会改变main中的实参值。
二、地址方式调用函数
传地址就是把变量的地址传给函数的形参,即函数形参用指针去接收这个地址(指针指向了真是变量的地址), 当形参指向地址上的内容修改时,会影响到实参(相当于实参本身的修改)。代码如下:
#include <stdio.h>
#include <stdlib.h>
void Swap(int *d1, int *d2)
{
int temp;
temp = *d1;
*d1 = *d2;
*d2 = *temp;
}
int main() {
int d1 = 10;
int d2 = 20;
printf("交换前:%d, %d\n", d1, d2); // 10, 20
Swap(&d1, &d2);
printf("交换后:%d, %d\n", d1, d2); // 20, 10
}
上面代码执行后,main函数里面的 d1和d2 的值发生了变化。这个传地址,其实也是值传递,只是这个值是地址。
三、通过指针作为函数参数
使用malloc函数分配空间,如果不正确传参,可能会发生错误。如下代码:
#include <stdio.h>
#include <stdlib.h>
void Passparam(int* param) // 指针变量也是变量
{
printf("function ¶m:%p\n", ¶m); // ¶m 指针变量在内存中的地址 00AFF880 与实参的地址是不一样的
printf("function param:%p\n", param); // 00000000 指针变量的值不变(函数传参时,实参与形参的值时相等的,即拷贝一份,但是他们在内存中存这个指针的地址是不一样的)
param = (int*)malloc(sizeof(int));
printf("function malloc param:%p\n", param); // 012D0550 为指针变量申请空间(分配地址)
*param = 55;
printf("after param:%d\n", *param); // 55
}
int main() {
int* param = NULL;
printf("main param:%p\n", param); // 00000000
printf("main ¶m:%p\n", ¶m); // 00AFF954
Passparam(param); // 传递值(这个值是一个指针)
printf("main param:%d\n", *param); // 读取访问权限冲突,param是nullptr
}
上述并没有输出想要的结果,虽然函数体中param申请了空间,得到了地址;但是main函数中的param没有分配到地址,所以指向的值没有发生变化。也就是Passparam函数中的int *param 是main函数中的int *param 副本,它是一个局部变量。修改函数中的值时,main中的值是不会变化的。
Passparam函数中(int *param)是一个值,若想输出正确结构,需要一个指向指针的指针来操作指针的地址
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
void Passparam(int** param) // 二级指针变量也是变量
{
printf("function ¶m:%p\n", ¶m); // ¶m 指针变量在内存中的地址 00AFFA58 与实参的地址是不一样的
printf("function param:%p\n", param); // 00AFFB2C 指针变量的值不变(函数传参时,实参与形参的值时相等的,即拷贝一份,但是他们在内存中存这个指针的地址是不一样的)
printf("function *param:%p\n", *param); // 00000000 // 二级指针的解引用是一级指针
*param = (int*)malloc(sizeof(int));
printf("function malloc param:%p\n", *param); // 00DB0550 为一级指针变量申请空间(分配地址)
**param = 55; // 一级指针的解引用赋值
printf("after param:%d\n", **param); // 55
}
int main() {
int* param = NULL;
printf("main before param:%p\n", param); // 00000000
printf("main ¶m:%p\n", ¶m); // 00AFFB2C
Passparam(¶m); // 传递值(这个值是指针的地址)
printf("main after param:%p\n", param); // 00DB0550 实参申请到了地址
printf("main param:%d\n", *param); // 55
}
总结
一句话:指针也是变量,当指针变量做为函数参数的时候,函数内部无法修改指针的值(就是地址不能在函数里面改变,就像一个整型变量传进去的时候,里面修改变量值,不影响函数外面变量的值),但是可以修改指针指向的变量和指针的值。