7

c语言入门5,一文彻底弄懂函数的形参和实参,再也不晕了

 4 years ago
source link: https://blog.popkx.com/c-language-entry-5-a-text-thoroughly-understand-the-function-of-the-parameters-and-arguments-no-longer-dizzy/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

c语言入门5,一文彻底弄懂函数的形参和实参,再也不晕了

发表于 2018-11-06 07:11:27   |   已被 访问: 277 次   |   分类于:   C语言   |   暂无评论

上一节,我们介绍了函数的形参和实参,知道了有参数的函数可以根据输入的数据,调整自己,能完成更加复杂的任务。在最后,我们举了一个初学者容易出错的例子,现在再把它写一遍,请和妹子一起看如下代码:

7df5da4809835689c3a85db00da77342.png
#include <stdio.h>

void add(int a)
{
    a=a+1;
}
int main()
{
    int p = 2;
    add(p);
    printf("p=%d", p);
    return 0;
}

程序员小明定义了一个 add 函数,他希望 add 函数可以将 p 加一,但是却失败了,以上程序输出的仍然是 p=2。

79e5166465fc03cb303fa94313172e44.png

上一节,有朋友(@蓝海星007)回复说:“所以 易错点 那个代码怎么写才对呢[笑哭]”。在回答这个问题之前,我们再详细说说小明写的代码为什么没有按照他的预期实现。

我们知道,程序运行在内存里,请看下图(暂时没有必要全部看懂),小明的程序运行时,系统分配给它的内存可以划分为好几个段。每调用一次函数,系统就会在栈里划分一块区域出来给这个函数使用。因为 main 函数是入口函数,所以栈一开始就要分配一块区域给它使用。接着,main 函数又调用了 add 函数,所以系统又在栈里划分了一块区域给 add 函数使用。

这里说的“一块区域”,程序员们常常称作“栈帧”。

b12b4edd989b60095834841ff8198db8.png

函数内部定义的局部变量,都在属于自己的栈帧里。所以小明的写的代码的 main 函数中的变量 p,在 main 函数的栈帧里(上图的最左边浅绿色小块里)。add 函数里的变量 a 在 add 函数的栈帧里(上图的第二块橘黄色小块里),在调用 add(p) 函数时,只是把 p 的值传给了 a,add 函数中无论如何在橘黄色小块中对 a 操作,也不会影响到浅绿色小块中的 p,所以,程序最终当然会输出 p=2,而不是小明设想的 p=3。

2b84bb64d90f6c76559cf2ea8ae9d2ef.png

事实上,在 add 函数执行完毕后,系统就把属于 add 函数的栈帧收回了。这个时候,add 函数中的变量 a,也就没了。用较专业的话说就是,函数在执行完毕后,局部变量就自动释放了,这就是原因。

栈帧与栈帧之间是不能互相访问的,所以 main 函数无法访问 add 函数里的 a,add 函数也无法访问 main 函数里的 p,想把 p 传给 add 函数,只能通过参数传递。

那么,怎样写才能实现小明的设想呢?

其实很简单,只要在 add 函数计算后,把橘黄色小块里的 a 传给浅绿色小块里的 p 就可以了。return 就可以实现这一的需求,我们来试一试:

#include <stdio.h>

int add(int a)
{
    a=a+1;
    return a;
}
int main()
{
    int p = 2;
    p = add(p);
    printf("p=%d", p);
    return 0;
}
d74cad88506c7ba98c8f5f1c732dc138.png

的确成功了。add 函数在结束自己之前,通过 return 把计算结果返回了,返回给谁了呢?从 main 函数可以看到,我们使用 p 接收了这个返回值,所以终于可以输出 p=3 了。如果像前两节一样把函数比作积木,那现在我们应该把积木玩活了,哈哈。

可能你又会问,不是说 add 函数执行完,它的栈帧就被系统收回了吗?怎么还能把计算结果返回呢?这个问题,我之前的文章已经解答了,感兴趣可以再看看:《》

阅读更多:   C语言


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK