shaoheshaohe 发表于 2021-6-10 17:10:43

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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
这里的自定义函数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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这里的自定义函数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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
上面的程序运行时会出现错误,因为自定函数中创建的参数,存储期只有自定义函数运行的这段时间,当自定义函数结束后,自定义函数中声明的变量会被释放。自定义函数返回的指针所指向的地址也就没有意义了。这是用主函数解引用指针会出现错误。

修改建议:
返回变量值
使用 static 将自定义函数存储在静态内存中,保证在程序退出前不被清除
字符串变量名作为参数,原字符串会被修改
#include<stdio.h>
void pass(char *pa)
{
    pa='a';
    printf("%s",pa);
}

int main(void)
{
    char list="Humphrey";
    pass(list);
    printf("%s",list);

    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
上面程序,自定义函数虽然没有返回值,但主函数中list被无意间修改了。
这是由于字符串是以指针传入函数,自定义函数是在原始地址上进行修改。
主函数再次访问就会出现修改过的结果。

修改建议:在传入函数前新建字符串副本,将副本传入函数,通过对副本的操作,实现功能。这样就不会出现原始字符串被修改的情况。
修改后的代码:

#include<stdio.h>
#include<string.h>
void pass(char *pa)
{
    pa='a';
    printf("%s",pa);
}

int main(void)
{
    char list="Humphrey";
    char mid;
    strcpy(mid,list);
    pass(mid);
    printf("%s",list);

    return 0;
}


shaoheshaohe 发表于 2021-6-10 17:10:53

https://blog.csdn.net/konghouy/article/details/80433443
页: [1]
查看完整版本: c语言函数传参