一、指向常量的指针:const int *
代码片段1:
const int val = 1; //定义一个int常量val,该常量初始化为1
int *p = &val; //错误,存在通过指针p修改val的风险
代码片段1,val是一个int类型常量,它的值不能被改变;p是一个指向int类型变量的普通指针,所以当p指向val时,存在通过p修改val的风险,导致编译报错。
代码片段2:
const int val = 1; //定义一个int常量val,该常量初始化为1
const int *p = &val; //正确,p指向常量对象val
*p = 2; //错误,不能修改p所指的const int对象的值
代码片段2,从右向左看const int *p这个声明,首先p是一个指针,指向一个int类型的常量对象,常量仅可在定义的时候赋值,所以p所指向的对象的值是不可改变的。上述代码第3行,通过解引用指针p修改它所指向的对象的值,会导致编译错误。
代码片段3:
const int val1 = 1; //定义一个int常量val1,该常量初始化为1
const int val2 = 2; //定义一个int常量val2,该常量初始化为2
const int *p = &val1; //正确,p指向常量对象val1
p = &val2; //正确,改变p所指向的const int对象
代码片段3,因p是一个指针,所以上述代码中,将p指向另外一个const int val对象是允许的。
tips:
指向常量的指针,指针自己觉得自己指向了常量,所以自觉地不去改变所指向的常量。
二、常量指针:int *const
代码片段4:
int val1 = 1; //定义一个int变量val1,该变量初始化为1
int val2 = 2; //定义一个int变量val2,该变量初始化为2
int *const p = &val; //正确,常量指针指p初始化为指向int变量val1
p = &val2; //错误,常量指针初始化后不能再指向其他对像
代码片段4,从右向左看int *const p这个声明,离p最近的声明符号是const,说明p是一个常量对象,下一个符号是*,说明p是一个常量指针,最后基本数据类型是int,即p是一个指向int的常量指针。与其他常量一样,常量指针p必须初始化,且初始化完成后不可指向其他对象。
代码片段5:
int val1 = 1; //定义一个int变量val1,该变量初始化为1
const int val2 = 2; //定义一个int常量val2,该常量初始化为2
int *const p1 = &val1; //正确,常量指针指p1初始化为指向int变量val
const int *const p2 = &val2; //正确,常量指针指p2初始化为指向int常量val2
*p1 = 2; //正确,把p1所指向的对象的值修改为2
*p2 = 3; //错误,p2是一个指向常量的指针
指针常量能否修改其所指向的对象的值,完全取决于其所指向的对象,在代码片段5中:p1指向变量val1,所以可以通过p1修改val1的值;p2是指向常量对象的常量指针,所以不论是p2自身所存储的地址,还是其所指向的对象val2的值都不可以改变。
三、总结
从右向左阅读const int *或int *const,如果声明const在数据类型前,则const修饰的是指针指向的对象,如果const在声明符号*之后,则const修饰的是指针本身。
-
const int *p:p是一个指向常量的指针,可以改变其指向的常量对象,但不能修改它所指向的常量对象的值。
-
int *const p:p是一个常量指针,p必须初始化,且初始化完成后不可指向其他对象,能否修改p所指向的对象的值,完全取决于其所指向的对象,如果对象本身不是常量则可修改,否则不能修改