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;
}
  • 10
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值