• 漫谈:C语言 值传递 函数参数 指针


    初级代码游戏的专栏介绍与文章目录-CSDN博客

            C语言麻拐得很。

            什么是变量?变量就是内存里面的一个东西,有值。

            什么是“值传递”?C语言函数参数调用都是值传递,就是把变量的值给函数。

    目录

    函数参数究竟是什么

    强调:参数是函数内部变量,传参相当于给内部变量赋值

    指针也是变量 

    &a不是地址传递,是生成临时变量

    强调:只有值传递,没有地址传递

    C++和其他语言的“引用”、“参考”是什么

    代码实测


    函数参数究竟是什么

            就是函数参数究竟是什么?这里面一个大坑。很多初学者对“值传递”、“传地址”很困惑,因为没人给他们解释“函数参数是函数内部定义的变量”,只不过必须在函数调用时给值而已,也就是赋初值。

            (注:以下代码为示意,不严格)

    1. int fun(int x)//这里定义了变量x
    2. {
    3. x=2;//这里操作变量x,跟函数调用的参数a没有任何关系
    4. }
    5. main()
    6. {
    7. int a=1;
    8. fun(a);//这里复制a的值给x,相当于执行了x=a;当然实际汇编代码是push 1,效果一样的
    9. }

            因为参数就是函数里面的变量,操作这个变量和外部变量没有关系,所以修改参数不会影响外部变量。 

    强调:参数是函数内部变量,传参相当于给内部变量赋值

    指针也是变量 

            什么是“指针”?内存的每个东西都有“地址”,存放地址的变量称为指针。

            如果一个函数参数是指针,函数调用的时候发生了什么?

    1. int fun(int * x)//这里定义了变量x,类型是指针
    2. {
    3. *x=2;//这里操作的是变量x里面的地址代表的内存,其实就是调用参数a
    4. x=2;//这是一个BUG,2是一个非法地址
    5. }
    6. main()
    7. {
    8. int a=1;
    9. int * b=&a;//为什么加这一句?因为本质上,&a就是生成了一个临时变量,类型为int*,值为a的地址
    10. fun(b);//这里复制b的值给x,因为b的值是&a,相当于执行了x=&a;
    11. }

    &a不是地址传递,是生成临时变量

            因为我们经常写“fun(&a)”这种代码,就觉得“&”表示了一种不同的传参方式,其实这是误解,这里的“&a”是一个运算,生成了一个临时变量,类型为“int*”,值为a的地址。

    强调:只有值传递,没有地址传递

            我们现在已经能够理解“只有值传递”这句话了,没有地址传递,地址只是变量的一种类型。函数能够修改外部数据是指针的妙处,不是传参的妙处。

    C++和其他语言的“引用”、“参考”是什么

            C++里面函数参数可以是“引用”,“引用”是什么?引用其实就是指针的另一种写法(当然严格讲引用和指针还是有不少区别的,但究其本质,就是一个语法糖)。

            其它高级语言的“变量”、“对象”、“参考”、“引用”等等是什么?其实还是C语言的变量和指针,因为世界本来如此。包装再漂亮,也解决不了null异常。

    代码实测

            看看这个代码:

    1. #include
    2. int f(int a)
    3. {
    4. a = 5;
    5. std::cout << &a << " " << a << std::endl;
    6. return a;
    7. }
    8. int main()
    9. {
    10. int a = 1;
    11. std::cout << f(a) << std::endl;
    12. std::cout << &a << " " << a << std::endl;
    13. }

            执行结果:

    1. 0000000B7775FAB0 5
    2. 5
    3. 0000000B7775FAD4 1

            第一行是在函数f内输出的,输出的地址是函数的参数a的地址,第三行是在main函数里输出的,输出的地址是main函数的变量a的地址,很清楚,两个地址是不一样的。

            我们再看看这个有点奇妙的代码:

    1. #include
    2. void f(int * a)
    3. {
    4. a = 0;
    5. std::cout << &a << " " << a << std::endl;
    6. }
    7. int main()
    8. {
    9. int a = 1;
    10. f(&a);
    11. std::cout << &a << " " << a << std::endl;
    12. }

             你可能会以为f里面给a赋值为0,外面的a就会变成0,看看实际输出:

    1. 0000008C212FF8D0 0000000000000000
    2. 0000008C212FF8F4 1

            并没有。想想为什么。

    (这里是结束)

  • 相关阅读:
    数据结构(二)基本概念和术语
    elasticsearch集群部署-实操
    uniapp+.net core 小程序获取手机号
    回归与聚类算法系列②:线性回归
    Tomcat基础与优化
    DNS协议隧道(1)
    Docker从入门到部署项目
    开关电源-PWM外设简介及MCC配置
    Azure Devops上模版化K8s部署
    JS教程之Electron.js设计强大的多平台桌面应用程序的好工具
  • 原文地址:https://blog.csdn.net/2301_77171572/article/details/132878538