• C语言指针及陷阱


    写这一篇博客的主要目的是记录在C语言编程的过程中,碰到的一些奇怪的关于指针的问题,通过对指针这一C语言特色变量的研究,为以后编写更为稳定的程序打下良好的基础,主要介绍了指针在函数值传递、地址转换等方面的相关陷阱!

    一、指针变量&函数形参

    1.首先如下所示为基本的函数形参指针传递值过程:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 int point(int *val){
     5     printf("Address Of ParamA=%x
    ",val); // Print the param val's address.
     6     *val = 10; // Change the value of val var.
     7 }
     8 int main(void)
     9 {
    10     int A = 1;
    11     printf("A=%d Address=%x
    ",A,&A); // Print the val and the Address of A.
    12     point(&A);
    13     printf("A'=%d Address'=%x
    ",A,&A); // Print the val and the Address of A.
    14 }

    如下所示为运行的结果:

    val的地址应该是&val,而函数中打印的是val地址中的内容,也就是A的地址了。

    这里我们可以看到,形参指向的地址0x65fe1c和main函数中A指向的地址是相同的,这里值得注意的是,对于A地址变量和val地址变量而言,其自身的存储地址是不同的,而地址中保存的指向a变量的地址是相同的,都是0x65fe1c,其自身的地址如下所示:

    #include <stdio.h>
    #include <stdlib.h>
    
    int point(int *val){
        printf("Address Of ParamA=%x
    ",&val); // Print the param val's address.
        *val = 10; // Change the value of val var.
    }
    int main(void)
    {
        int *A;
        int a = 1;
        A = &a;
        printf("A=%d Address=%x
    ",*A,&A); // Print the val and the Address of A.
        point(A);
        printf("A'=%d Address'=%x
    ",*A,&A); // Print the val and the Address of A.
    }

    Notice:运行的结果如下,这里可以看到形参的地址和main中A的地址是不同的,当然他们指向了同一个地址空间,这就是为什么指针传递能够改变数值,因为传到函数中的地址是待改变的var变量的地址,因此完成了数值的改变,这也就是所谓的形参实际上是地址参数的一个副本,他不是完全相同的,而是地址不同指向地址相同的两个不同的变量,当函数完成以后,这个形参地址变量副本将会被回收

    形参地址和传入地址变量的地址不同。

     同时可以看到,通过在函数中改变val 的值确实达到了传递参数的效果。

    2.在函数中改变形参指向地址的陷阱

     1 #include <stdio.h>
     2 
     3 int point(int *val){
     4     int *P = (int *)malloc(sizeof(int)*3); // Alloc a new mem in func-point
     5     printf("Address Of ParamA=%x
    ",val); // Print the param val's address.
     6     *P = 10;
     7     val = P;
     8     printf("Address Of ParamA=%x
    ",val); // Print the param val's address.
     9 }
    10 int main(void)
    11 {
    12     int *A;
    13     int a = 1;
    14     A = &a;
    15     printf("A=%d Address=%x
    ",*A,&A); // Print the val and the Address of A.
    16     point(A);
    17     printf("A'=%d Address'=%x
    ",*A,&A); // Print the val and the Address of A.
    18 }

    程序运行结果如下所示:

     可以看到在主函数中显示的A的地址0x65fe18居然不等于函数形参未改变之前的地址0x65fe14,经过Debug对程序进行调试,发现地址起始是一样的,都是0x65fe14,至于为什么会出现打印结果和Debug结果的不同还有待分析。

    重要的是,在值传递之前,对形参中指向的地址进行了重新的赋值,此时形参副本将不会指向外部数据的地址,从此无法改变外部数据值,从而无法完成值传递,因此,一定要注意对形参进行指针赋值的情况,否则将造成数据无法传递的情况。(此时新的地址0x7713f0指向的地址的内容为10.)

    二、数组地址值传递及分析

    1.二维数组&多维数组的构造方式

    2.如何传递数组到函数中

    未完待续!

  • 相关阅读:
    django 项目运行时static静态文件不能加载问题处理
    django 项目运行时media静态文件不能加载问题处理
    django 的用户验证及登录状态保持
    django 2.0 中URL的include方法使用分析
    auth.User.groups: (fields.E304)
    web理论知识--HTML结构及标签
    数据库相关--mysql中的单表查询
    python基础下的数据结构与算法之链表
    python基础下的数据结构与算法之顺序表
    Nginx 日志分析命令
  • 原文地址:https://www.cnblogs.com/uestc-mm/p/13553623.html
Copyright © 2020-2023  润新知