• 常指针与指针常量的区别(转帖)


       三个名词虽然非常绕嘴,不过说的非常准确。用中国话的语义分析就可以很方便地把三个概念区分开。

    一) 常量指针。

    常量是形容词,指针是名词,以指针为中心的一个偏正结构短语。这样看,常量指针本质是指针,常量修饰它,表示这个指针乃是一个指向常量的指针(变量)。

    指针指向的对象是常量,那么这个对象不能被更改。

    在C/C++中,常量指针是这样声明的:

    1)const int *p;

    2)int const *p;

    常量指针的使用要注意,指针指向的对象不能通过这个指针来修改,可是仍然可以通过原来的声明修改,也就是说常量指针可以被赋值为变量的地址,之所以叫做常量指针,是限制了通过这个指针修改变量的值。例如:

     int a = 5;

     const int b = 8;

      const int *c = &a; // 这是合法的,非法的是对c的使用

      *c = 6; // 非法,但可以这样修改c指向的对象的值:a = 6;

       const int *d = &b; // b是常量,d可以指向b,d被赋值为b的地址是合法的

      细心的朋友在使用字符串处理函数的时候,应该会注意到这些函数的声明。它们的参数一般声明为常量指针。例如,字符串比较函数的声明是这样的:

     int strcmp(const char *str1, const char *str2);

     可是这个函数却可以接收非常量字符串。例如这段程序:

     char *str1, *str2;

     str1 = "abcde1234";

     str2 = "bcde";

     

        if(strcmp(str1, str2) == 0)

        {

            printf("str1 equals str2.");

        }

    str1和str2的内容显然是可以更改的,例如可以使用“str1[0] = x;”这样的语句把str1的内容由“abcde1234”变为“xbcde1234”。因为函数的参数声明用了常量指针的形式,就保证了在函数内部,那 个常量不被更改。也就是说,对str1和str2的内容更改的操作在函数内部是不被允许的。(就目前的应用来看,我觉得设置常量指针就是为函数参数声明准 备的,不然还真不知道用在什么地方呢,呵呵!)

      虽然常量指针指向的对象不能变化,可是因为常量指针是一个变量,因此,常量指针可以不被赋初始值,且可以被重新赋值。例如:

    const int a = 12;

     const int b = 15;

     const int *c = &a; // 为了简化代码,很多人习惯赋初始值

      const int *d;

      d = &a; // 这样当然是可以的

       c = &b; // 虽然c已经被赋予初始值,可是仍然可以指向另一个变量

     特点是,const的位置在指针声明运算符*的左侧。只要const位于*的左侧,无论它在类型名的左边或右边,都声明了一个指向常量的指针,叫做常量指针。

    可以这么想,*左侧是常量,指针指向的对象是常量。

    二) 指针常量 

     指针是形容词,常量是名词。这回是以常量为中心的一个偏正结构短语。那么,指针常量的本质是一个常量,而用指针修饰它,那么说明这个常量的值应该是一个指针。

     指针常量的值是指针,这个值因为是常量,所以不能被赋值。

     在C/C++中,指针常量这样声明:

    int a;

    int *const b = &a; //const放在指针声明操作符的右侧

     只要const位于指针声明操作符右侧,就表明声明的对象是一个常量,且它的内容是一个指针,也就是一个地址。上面的声明可以这么读,声明了一个常量b,它的值是变量a的地址(变量a的地址,不就是指向变量a的指针吗)。

     因为指针常量是一个常量,在声明的时候一定要给它赋初始值。一旦赋值,以后这个常量再也不能指向别的地址。

    虽然指针常量的值不能变,可是它指向的对象是可变的,因为我们并没有限制它指向的对象是常量。

     因此,有这么段程序: 

     char *a = "abcde1234";

      char *b = "bcde";

      char *const c = &a;

      下面的操作是可以的。

      a[0] = 'x'; // 我们并没有限制a为常量指针(指向常量的指针)

     或者

      *c[0] = 'x' // 与上面的操作一致

     三)指向常量的指针常量

     顾名思议,指向常量的指针常量就是一个常量,且它指向的对象也是一个常量。

    因为是一个指针常量,那么它指向的对象当然是一个指针对象,而它又指向常量,说明它指向的对象不能变化。

     在C/C++中,这么声明:

      const int a = 25;

      const int * const b = &a;

     看,指针声明操作符左边有一个const,说明声明的是一个指向常量的指针。再看,指针声明操作符右边有一个const,说明声明的是一个指针常量。前后都锁死了,那么指向的对象不能变,指针常量本身也不能变。细细体味,相信能得其道,下面就不赘述了。

    用一个例子作为总结。虽然字符指针与其它指针的本质是一样的,可是因为字符指针常用来表示字符串,常不好理解。下面就用字符指针来举例。

     char *a = "abcde1234";

        const char *b = "bcde"; // b是指向常量字符串的指针变量

        char *const c = &a;  // c是指向字符指针变量的常量

        const char *const d = &b; // d是指向字符常量的指针常量

      问题来了。

    1)问:因为a是变量,a可以赋值为其它值,如"12345abc"。那么c指向a,当a变化了,c指向什么呢?

     答:仍然指向"abcde1234"。虽然a可以指向别的字符串,可是c仍然指向"abcde1234",也就是a开始指向的对象。

    2)问:a是变量,可以改变a的内容。那么当执行了“a[0] = 'x';”后,c会怎样呢?

     答:c当然还指向a初始指向的字符。不过,这个字符已经变成了'x'。

     3)问:b是指向常量的指针变量,当b指向别的字符串,d怎么样?

     答:d仍然指向b初始的字符串。

     4)问:b可以变化,b指向的字符不能变化,也就是说b[0]不能被重新赋值,可是b[1]可以被重新赋值吗?

     答:原则上b指向的字符是常量,并没有限制下一个字符,应该可以被赋值。可是因为你使用字符串进行了初始赋值,而且编译器是静态编译的,C/C++程序就把b当作字符串指针来处理了,因此,当对下一个字符进行赋值时,编译不能通过。

     其他问题,欢迎补充。

     我编了这样的口诀,记住,应该不难:

     const(*号)左边放,我是指针变量指向常量;

     const(*号)右边放,我是指针常量指向变量;

      const(*号)两边放,我是指针常量指向常量;

      指针变量能改指向,指针常量不能转向!

      要是全都变成常量,锁死了,我不能转向,你也甭想变样!

  • 相关阅读:
    POJ 1953 World Cup Noise
    POJ 1995 Raising Modulo Numbers (快速幂取余)
    poj 1256 Anagram
    POJ 1218 THE DRUNK JAILER
    POJ 1316 Self Numbers
    POJ 1663 Number Steps
    POJ 1664 放苹果
    如何查看DIV被设置什么CSS样式
    独行DIV自适应宽度布局CSS实例与扩大应用范围
    python 从入门到精通教程一:[1]Hello,world!
  • 原文地址:https://www.cnblogs.com/bayonetxxx/p/1447966.html
Copyright © 2020-2023  润新知