背景:
昨晚写完一个关于位运算的小函数,实现后验证发现逻辑没有问题,但是无论如何都无法将结果带出函数给其他运算使用…
分析过程:
当初的思路认为是实参为局部变量的原因,改成全局变量后,问题依然存在.
后来debug了一晚上,看了很多文章和代码,才发现是函数调用,实参跟形参之间单向传递的问题
即实参 => 形参, 形参 ≠>实参
;实参可以传递数值给形参,但是形参不会传递数值给实参,且实参是函数内部局部变量,在函数调用完毕后,在内存中被销毁
// 验证代码
#include <stdio.h>
int i = 1; // 全局变量
void Add(int x)
{
x++; /*
** 注意:
** 实参将数值传递给形参后,形参在函数内的操作不会影响到实参(即实参和形参之间是单向传递!)
** 实参 -> 形参 (可以)
** 形参 -> 实参 (不可以)
** 且形参在函数调用结束后,便被销毁
**
**
*/
}
int main()
{
/* Write C code in this online editor and run it. */
printf("%d\n", i); // i = 1
Add(i); // i在函数Add(int x)作为实参传递值给形参x,虽然形参在函数内自增1
// 但因为形参不会传递值给实参,且在函数调用完毕后被销毁(作用域)
// 所以在调用函数前后,i的值没有发生变化
printf("%d\n", i); // i = 1
return 0;
}
延伸问题:
为什么在使用stm8s官方库函数的时候(函数无返回值),将实参传递给某函数,退出函数,实参跟着发生了变化呢?
分析过程:
重新回头看了一下stm8s库函数的具体实现,发现传递给函数的参数并不是普通的变量,而是一个
指针
。其指向的是一个数值的地址,修改的是存放在地址的值,即使形参(指向值的地址)在退后函数后被销毁,存放在地址的值也会依然存在,因为被销毁的仅仅的指向它的地址!
所以可以解释为什么在调用无返回值的函数时,在函数内部修改指针指向的数值,退出函数后,数值会跟着发生变化
// 验证代码
#include <stdio.h>
void Test(int* a, int b)
{
*a = 1; // 形参a修改实参pa指向的值
b = 1;
}// 形参a被销毁,但指向的值仍在内存中保存,即为主函数的a
int main()
{
/* Write C code in this online editor and run it. */
int a = 0;
int* pa = &a; // 指针pa存放a的地址
int b1 = 0;
Test(pa, b1); // pa作为实参传入函数
printf("%d %d\n", *pa, b1); // 解引用符号*读取pa指向的值
return 0;
}
解决方案:
- 将函数
无返回
值改成函数有返回值
,且在函数调用结束后将返回值赋值,得到我们想要的结果- 将
形参
改为指针
,修改指针指向的值,在函数退出后扔存储在内存中,而形参(指向数值的地址)被销毁