C语言传参
引入:
- 自定义函数的使用,使整个程序模块化。
- 每个函数都解决一个小问题,当我们编写好函数后,就把精力转移到,函数之间的逻辑关系上。不必再纠结每一条语句,这样大大提高了编程的效率。
- 当需要实现相同功能时,可以将函数多次调用,提升代码的复用性。
- 同时在程序出现问题时,可以快速定位,解决问题。
不过对于函数的参数调用时常会出现问题。
-
1.使用中出现的两种情况
-
主函数的值没有被修改(变量的传递)
#include < stdio.h >
int p(int a) {
a = 20;
return a;
}
int main(void) {
int a;
a = 10;
p(a);
printf("%d", a); //这里的a值没有被修改,依然是10
return 0;
}
这里的自定义函数p,接收一个int类型的参数,并定义为a。
虽然自定义函数和主函数的变量名,都为a,但是这里的a是两个变量。
虽然函数也将a返回了,但是主函数并没有接收,忽略了p的返回值。
所以主函数的a依然是10
- 主函数的值被修改了(指针的传递)
#include < stdio.h >
void p(int * w) { * w = 20;
}
int main(void) {
int a;
int * s = & a;
p(s);
printf("%d", a);
return 0;
}
这里的自定义函数p,接收一个int类型的指针,命名为w。
虽然这里的指针w,和主函数的指针s,名称不一样,但是他们两个都指向了内存中a的地址。
通过指针的解引用,在内存中修改相关数值。
主函数再次访问a时,就已经是修改过的值,即使自定义函数没有返回值,a的值已经改变。
所以主函数的打印的结果为20
-
2.从内存的角度分析上面的两种情况
-
程序运行过程当中,所有的变量都是在内存中存储的
-
当自定义函数创建时,定义的形参,都会分配新的空间(即使参数名称相同)
-
新空间存储的内容,为上一级函数传入的内容。
- 传入变量值时,新空间记录传入值。
主函数实参地址存:10 / 自定义形参地址存:10
两个地址存的数值相同,但两者没有联系,修改形参的值,实参值并不会修改- 传入变量指针时,新空间记录指针地址
主函数变量地址存:10
主函数指针指向:变量地址 自定义指针指向:变量参地址
主函数指针的地址,和自定义函数指针的地址虽然不同
但两者都指向了需要修改的内容,通过指针修改内存的值。
- 3.不同的应用场景
函数传递参数
- 一般用于数字计算,不使用指针,防止无意间修改内存的值
- 思路清晰,更好理解
函数传递指针
- 需要修改多个上级函数的值
- 需要跨函数修改内容(两个函数之间没有调用关系)
- 结构体等内存较大的传递,使用指针缩短传递时间
- 4.函数参数的几种错误
自定义函数创建的变量,返回指针参数
#include<stdio.h>
int *creat(void)
{
int a;
int *p = &a;//应该为:static int *p = &a;
a=20;
return p;
}
int main(void)
{
int *place;
place=creat();
printf("%d",*place);
return 0;
}
上面的程序运行时会出现错误,因为自定函数中创建的参数,存储期只有自定义函数运行的这段时间,当自定义函数结束后,自定义函数中声明的变量会被释放。自定义函数返回的指针所指向的地址也就没有意义了。这是用主函数解引用指针会出现错误。
- 修改建议:
- 返回变量值
- 使用 static 将自定义函数存储在静态内存中,保证在程序退出前不被清除
字符串变量名作为参数,原字符串会被修改
#include<stdio.h>
void pass(char *pa)
{
pa[1]='a';
printf("%s",pa);
}
int main(void)
{
char list[10]="Humphrey";
pass(list);
printf("%s",list);
return 0;
}
上面程序,自定义函数虽然没有返回值,但主函数中list被无意间修改了。
这是由于字符串是以指针传入函数,自定义函数是在原始地址上进行修改。
主函数再次访问就会出现修改过的结果。
- 修改建议:在传入函数前新建字符串副本,将副本传入函数,通过对副本的操作,实现功能。这样就不会出现原始字符串被修改的情况。
修改后的代码:
#include<stdio.h>
#include<string.h>
void pass(char *pa)
{
pa[1]='a';
printf("%s",pa);
}
int main(void)
{
char list[10]="Humphrey";
char mid[10];
strcpy(mid,list);
pass(mid);
printf("%s",list);
return 0;
}
- 感谢你赐予我前进的力量