常量指针 和 指针常量

0 backgroud

    在coding的时候遇到一些const修饰的指针和对象,不清楚用法和意义,所以整理了一下。


1 指针类型

    指针可以指向很多对象,整形,浮点形,结构体形等等。有时为了得到通用函数,可以设置指针为void形,而在使用的时候可以强制转为需要的形式。比如堆分配函数malloc/calloc函数:    

void * malloc(size_t size);
int *pint = malloc(sizeof(int) * 10);
char *pchar = malloc(sizeof(char) * 10);
double *pdouble = malloc(sizeof(double) * 10);

    这里可以看到,因为malloc()返回为void *形,所以在代码申请到堆的时候会隐式地转换为需要的类型。下面为一个简单的demo参考,其中p0是因为定义为 void*形,但是要printf输出所以要显式地进行类型转换。

    // p0 是一个可指向任何类型的指针
    void *p0;
    int m0 = 0;
    p0 = &m0;
    printf("%d\n", *(int *)p0);


    // p1 是一个可指向 int型的指针
    int *p1;
    int m1 = 1;
    p1 = &m1;
    printf("%d\n", *p1);


2 常量指针

    关于常量指针,形式为const int* p;它指示着p不可以修改指向的数据的值(指向的数据为常量),下面有一个例子

		int sizeof(void *p)  
		{  
		    // blablablabla  
		}  
		int sizeof2(const void *p)  
		{  
		    // blablablabla  
                }  

    sizeof 和 sizeof2 都是计算p的空间,显然这个函数是不需要,也是不可以修改p的数据的。那么我们可以把p用const修饰,这样在函数体内部就不可以对p的数据进行修改,阅读者也更加方便理解。


3 指针常量

    关于指针常量,形式为int* const p;表示p是一个常量,但它是一个指针。所以p是一个指针,但它指向的地址不能修改。

    // p5 是一个 指针常量, 既然是常量那么指针指向的对象唯一,但数据可以修改(类似引用)。
    int m5 = 5;
    int* const p5;  // 给p5分配空间,但是不给他赋初值,所以指针p5指向一个随机地址
    //*p5 = m5;     // when running, segment default  //对随机地址赋值,可能造成栈溢出
    //p5 = &m5;     // error // p5是一个常量,是不可以修改值的
    printf("&p5: %p,  p5: %p\n", &p5, p5);  


4 code demo

    上面为关于指针常量和常量指针的介绍,下面提供一个可运行的demo。大家可以自己测试一把:)

#include <stdio.h>

int main(){
    // p0 是一个可指向任何类型的指针
    void *p0;
    int m0 = 0;
    p0 = &m0;
    printf("%d\n", *(int *)p0);


    // p1 是一个可指向 int型的指针
    int *p1;
    int m1 = 1;
    p1 = &m1;
    printf("%d\n", *p1);

    // p2 p3 是一个 常量指针 指向常量的指针。
    // p2 是一个可指向任何类型的指针,被const修饰, 不可以修改指向的对象值,但是可以指向其他的对象。
    const void *p2;
    int m2 = 2;
    p2 = &m2;
    //*p2 = 3;	//error
    printf("%d\n", *(int*)(p2));

    // p3 是一个指向int形的指针,被const修饰,不可以修改指向的对象值,但是可以指向别处
    const int *p3;
    int m3 = 3;
    p3 = &m3;
    //*p3 = m3; //error
    printf("%d\n", *p3);

    // int const *p  === const int *p  等价,不可以修改指向的值,但可以指向不同对象
    int const *p4;
    int m4 = 4;
    p4 = &m4;
    //*p4 = m4;
    printf("%d\n", *p4);

    // p5 p6 是一个 指针常量, 既然是常量那么指针指向的对象唯一,但数据可以修改(类似引用)。
    int m5 = 5;
    int* const p5;  // 给p5分配空间,但是不给他赋初值,所以指针p5指向一个随机地址
    //*p5 = m5;     // when running, segment default  //对随机地址赋值,对造成栈溢出
    //p5 = &m5;     // error // p5是一个常量,是不可以修改值的
    printf("&p5: %p,  p5: %p\n", &p5, p5);  


    int m6 = 6;
    int* const p6 = &m6;// 给p6分配空间,并且把m6的地址给他
    *p6 = 1;
    printf("%d\n", *p6);   // ok
    printf("&p6: %p,  p6: %p,  *p6: %d      &m6: %p,  m6: %d\n", &p6, p6, *p6, &m6, m6);  

    return 0;

}

5 reference

    http://www.cnblogs.com/lizhenghn/p/3630405.html

    https://blog.csdn.net/stpeace/article/details/45349757





猜你喜欢

转载自blog.csdn.net/mistakk/article/details/80268436