• 关于C语言指针几个容易混淆的概念


    前言:
      大多数学习过C/C++或者正在学习的同学在对指针概念把握时,总是感觉不太明了,小弟我也不例外啊,于是翻开资料复习整理一下,并把自己的学习心得拿出来供大家分享,讨论。 基本概念掠过,主要来探讨一下容易混淆的几个概念。

    1.指向常量的指针与指针常量

      a.指向常量的指针
        如const char * pStr是指向常量的指针变量,既此定义的变量是一个指向字符数组的指针变量,我们可以对其进行再次赋值,但该指针指向的地址块的值不能改变。请看  下面的例子:

    char ch[5]="lisi“;
    const char * pStr=ch;   //pStr 是指向字符数组的指针变量
    pStr="wangwu";          //这是没有任何问题的
    *pStr="w";              //此处编译时会报错,因为我们通过指向*符找到pStr所指向的内存地址块是常量所占有,所以不能再次赋值。

      指向常量的指针主要用于作为函数的参数,如定义一个画线函数:

    void DrawLine(const CPoint *pt1,const CPoint * pt2){
       // .....
    }

      通过参数pt1, pt2获得两个点的指针,在函数体中我们可以获取pt1->x,pt1->y,但是我们无法进行 pt1->x=3等赋值操作,从而保证了数据的一致性与安全性。

      b.指针常量
        下面我们对比性地来看指针常量 如:

    char * const pStr;

        此处定义的是一个指针常量,有的教材上叫它常量指针,个人觉得还是叫它指针常量比较容易理解记忆既然是常量,在定义时初始化之后,就不能对其再赋值,但其指向的  地址块的值可以改变。

    char ch[5]="lisi";
    char * const pStr=ch;
    pStr="zhangsan";    //错误
    *pStr='w';           //正确

        由于const char * pStr与 char * const pStr外观上太相似,所以和容易弄混,我们可以通过下面的方法来记忆,但仅供参考,方便记忆而已,没有理论根据。

        首先看char * const pStr中的 const修饰的是变量名pStr,所以pStr是指针常量而const char * pStr中的const后面是(char * pStr), pStr已经被指向符 * 修饰   过,所以可以理解为const修饰的pStr所指向的地址块,该地址块为常量,所以const char * pStr是指向常量的指针变量
      如果你觉得上面讲还行,那就继续看下面的吧.

    2.指针数组和指向数组的指针

      a.数组

        先我们先来探讨一下关于数组的问题,我们先定义一个数组

        char ch[4]="abc"; 

        我们可以对其进行
        *(ch+0)='e';//等价于ch[0]='e';的合法操作
        但是,接下来
        char ch2[4]="123";

        ch=ch2; //编译时会报错

        这是为什么呢?因为,数组名ch其实就是一个指向字符的指针常量,下面我们我们来做一个实验:    

    #include <stdio.h>
    #include <malloc.h>
    static void main()
    { 
        char ch[4]="abc";
        char * const pCh=(char *)malloc(4*sizeof(char));   //申请地址空间 并将说空间首地址赋给pCh
        *(pCh+0)='a';
        *(pCh+1)='b';
        *(pCh+2)='c';
        *(pCh+3)='';
        printf("%s   %s",ch,pCh);
    }

        如果你一眼看到char * const pCh就能说出pCh是一个指针常量的话,说明天才的你已经理解前面所讲的了,我感到万分荣幸。这个程序的结果是 :abc  abc 

        例子中 char ch[4] 与 char * const pCh=(char *)malloc(5*sizeof(char));  的效果是一样的,c内部处理上,个人认为应该也是一样的,所以说数组名本质就是就是一  个指针常量。

       b.指针数组

        很好理解 就是数组里存放的是指针 如:
        char * week[7]={"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}
        该数组中存放的是指向字符串的指针

      c.指向数组的指针

        如:
        int  (*p)[3];  // 注意括号可不能丢了 
        那么p就是一个指向大小为3数组的指针变量,我们知道数组名就是指针指向数组的指针就是一个二级指针

        int  a[][3]={1,2,3,4,5,6};
        我们知道a是一个二维数组,可以进行以下操作
        printf("%d  ",*(*(a+0)+1));
        printf("%d  ",*(a[0]+2));
        printf("%d  ",a[1][2]);
        结果分别是2  3  6
        这是因为二维数组名是二级指针常量,接下来我们的最后一个小实验

    #include <stdio.h>
    static void main()
    { 
        int  a[][3]={1,2,3,4,5,6};
        int  (*p)[3]=a;
        printf("%d  ",*(*(p+0)+1));
        printf("%d  ",*(p[0]+2));
        printf("%d  ",p[1][2]);
    }

        将会的到同样的结果2  3  6 。

     

    Talking with giants
  • 相关阅读:
    heapq of python
    array of python
    Unittest of Python
    事件驱动型工作流 vs 引擎型工作流
    airflow
    WPF 调试触发器
    WPF 使用Popup和TreeView实现树状下拉框
    Oracle : ORA 00933: SQL command not properly ended
    PostgreSQL && PostGIS
    基于ArcGIS开发3D立方体空间关系判断
  • 原文地址:https://www.cnblogs.com/newcooler/p/3603969.html
Copyright © 2020-2023  润新知