zoukankan      html  css  js  c++  java
  • C语言的传值与传址~~

    Linux中万物皆文件。

    js中万物皆对象。

    而我觉得编程世界,万物皆内存,无非是读写内存操作,我们要找到我们想要用到的资源,那么一定要先找到内存地址,再去拿出来我们正真想要用的值~~

    下面用一个简单的交换程序来说明传值与串址的区别。

    (1)传值

     1 void swap(int a,int b);
     2 void swap1(int* a, int* b);
     3 int main()
     4 {
     5     /*
     6     C语言传参机制
     7     */
     8     int a = 100;
     9     int b = 200;
    10     swap(a, b);
    11     printf("主函数中a=%d
    ", a);
    12     printf("主函数中b=%d
    ", b);
    13     
    14         getchar();
    15     }
    16     
    17 void swap(int a, int b) {
    18     int temp;
    19     temp = a;
    20     a = b;
    21     b = temp;
    22     printf("传值swap普通函数中a=%d
    ", a);
    23     printf("传值swap普通函数中b=%d
    ", b);
    24 }

    运行结果:

     说明传值的情况下无法实现交换值的功能,因为答案很简单,编程世界万物皆内存,我们在主函数中开辟的a,b的内存地址和被调用函数swap()中a,b的地内存地址是不一样的,

    所以我们只是在swap中实现值的交换,而没找到主函数的a,b的内存,再对值进行交换,所以归根没有操作主函数的a,b。所以结果就如上面一样。

    (2)址传递

    void swap(int a,int b);
    void swap1(int* a, int* b);
    int main()
    {
        /*
        C语言传参机制
        */
        int a = 100;
        int b = 200;
        swap1(&a, &b);
        printf("主函数中a=%d
    ", a);
        printf("主函数中b=%d
    ", b);
        
            getchar();
        }
    
    void swap1(int* a, int* b) {
        int temp;
        temp = *a;//*与&互相抵消,这里意思是100赋值给temp
        *a = *b;
        *b = temp;
        printf("传址swap函数中a=%d
    ", *a);
        printf("传址swap函数中b=%d
    ", *b);
    }

    运行结果:

     这里结果和上面不同也很简单,这里我们使用了指针,指针用来指向你要的资源地址,我们把a,b以&a,&b传入,所以swap1当然拿到我们主函数中的a,b地址了,此时swap1函数

    里面的操作,实际上是对于a,b的值进行交换。打个比方,就比方我们是酒店经理,然后客人甲,与客人乙,说要交换房间(原本甲住在a房间,乙住在b房间),所以交换后,

    甲住在b房间,乙住在a房间。

    (3)传址2(无意间发现,记录一下)

     1 void swap(int a,int b);
     2 void swap1(int* a, int* b);
     3 int main()
     4 {
     5     /*
     6     C语言传参机制
     7     */
     8     int a = 100;
     9     int b = 200;
    10     swap1(&a, &b);
    11     printf("主函数中a=%d
    ", a);
    12     printf("主函数中b=%d
    ", b);
    13     
    14         getchar();
    15     }
    16 
    17 void swap1(int* a, int* b) {
    18     int *temp;//此处与上面不一样
    19     temp = a;
    20     a = b;
    21     b = temp;
    22     printf("传址swap函数中a=%d
    ", *a);
    23     printf("传址swap函数中b=%d
    ", *b);
    24 }

    运行结果:

     运行结果分析,你会发现,我们虽然拿到a,b的地址了,但是我们没有实现交换a,b值的功能,思考一下很简单,因为我们swap函数中做的操作不是交换值,而是交换址,

    原本我们如果实现地址的交换,那么a,b的值理论上可以成功交换。但是这里我猜想内存地址是一个固定的,不可交换的,我们可以对内存中的值进行

    操作,我们是不能对址进行修改的,打比方,我们酒店101和102号房间的位置对调一下可以吗,答案也是不可能,因为总不能把它砸了,重新建筑吧。

    所以,我们在原来上面加上打印地址操作,

     

    结果我的猜想只对了一半,因为我说的是不能进行交换址,这个正确,但是这里它们进行操作的是swap函数中a,b的内存地址,我原本猜想是可以成功拿到a,b的地址,实际上我觉得它已经拿到主函数的a,b地址了,直不过在swap函数中进行值输出时,采用了就近原则,而交换地址这种不合法操作为什么不会报错,我又有了一个猜想,可能是如果交换地址,那就默认交换地址中的值

    所以实际上,交换的不是主函数传过来的地址,交换的是swap函数重新分配的地址,我们只是对swap函数进行操作,

    并没有对主函数进行操作,所以主函数中a,b值当然不能成功交换……

    红色字体,推翻蓝色的猜想:

     1 int main()
     2 {
     3     /*
     4     C语言传参机制
     5     */
     6     int a = 100;
     7     int b = 200;
     8     int *a1;
     9     int *b1;
    10     int *temp;
    11     a1 = &a;
    12     b1 = &b;
    13     printf("交换前主函数中a1的地址=%d
    ", a1);
    14     printf("交换前主函数中b1的地址=%d
    ", b1);
    15     
    16     temp = a1;
    17     a1 = b1;
    18     b1 = temp;
    19 
    20     printf("主函数中a=%d
    ", a);
    21     printf("主函数中b=%d
    ", b);
    22     
    23     printf("交换后主函数中a1的地址=%d
    ", a1);
    24     printf("交换后主函数中b1的地址=%d
    ", b1);
    25         getchar();
    26     }

    运行结果:

     我们可以看出,地址是可以交换的,所以蓝色字体无效,而为什么地址可以交换,为什么对于程序3主函数的a,b内存拿到的情况下,无法进行址交换呢,因为swap函数运行的,操作的是自己内部的a,b的内存,并没有操作主函数的a,b内存,所以主函数a,b值不变化。

    最后总结:

    (1)上面的不管是程序1还是程序2,实际上都是进行值交换,只不过是基于不同方式进行值交换而已。程序1使用传值方式,在swap函数中再进行值交换,此时实际交换的是a,b的影分身,而实际上主函数的a,b并没有进行操作;而程序2,我们采用了址传递a,b,再通过主函数的a,b地址进行值交换,这里swap函数中成功对主函数的a,b进行值交换。

    (2)而对于第3个程序,我们想要实现的无非就是址交换,把地址交换,但实际上,我们交换的还是swap函数的a,b地址,没有对主函数a,b进行操作,所以主函数a,b值无变化。

    (3)对于猜想部分,即蓝色字体,大家看的时候,看看就好,因为毕竟是我自己的想法。

  • 相关阅读:
    Fix Installing .NET Framework 3.5 failed Error Code 0x800F0954 on Windows 10
    RHEL8安装五笔输入法
    Enable EPEL and Local Repository on RHEL8
    Why is Yum Replaced by DNF?
    检查Linux服务器是否被攻击的常用命令及方法
    IDEA 主题
    IDEA 如何显示一个类中所有的方法
    Appium 安装以及安装过程中遇到的问题
    Maven 如何发布 jar 包到 Nexus 私库
    java泛型的基本使用
  • 原文地址:https://www.cnblogs.com/hmy-666/p/12839760.html
Copyright © 2011-2022 走看看