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)对于猜想部分,即蓝色字体,大家看的时候,看看就好,因为毕竟是我自己的想法。

  • 相关阅读:
    linux下导入、导出mysql 数据库命令
    MapReduce工作原理(简单实例)
    BloomFilter ——大规模数据处理利器
    huawei机试题目
    二叉树操作集锦
    表达式计算的中序转后序
    用 JavaScript 修改样式元素
    网页中的表单元素
    使用网络字体作为矢量图标
    CSS 的 appearance 属性
  • 原文地址:https://www.cnblogs.com/hmy-666/p/12839760.html
Copyright © 2011-2022 走看看