首先快速复习一些基础。
考虑下面的声明兼定义式:
int p = 10;
p的基础数据类型是int。
考虑下面的声明兼定义式:
const int a = 10;
a的基础数据类型是int,a是一个常量对象,所以必须在声明时初始化。
考虑下面的语句:
const int a = 10;
int *ptr = &a;
错误,不能将整型指针指向整型常量对象。
const int* ptr = &a; //正确!
注意,指针的左侧若有const修饰符,则称它为“指向常量的指针”。顾名思义,当你声明并初始化了这样的指针,编译器便默认该指针指向的是“一个常量”。为什么这里的“一个常量”要打双引号呢?因为其实所谓的“指向常量”只是该指针“自己认为”的,实际上你可以将“指向常量的指针”指向一个非常量对象,比如:
double x = 10.1;
const double* ptr = &x;
在这里,ptr这个“指向常量的指针”以为自己指向的是一个常量,实际上操作者可以自己对x进行随意赋值,只是不能用ptr指针对x进行修改罢了。
Hint: 形如const type*的指针的特点是不能改变所指对象的值
考虑下面的声明兼定义式:
double num = 1.1;
double* const ptr = #
注意,该指针的右侧有const修饰符,则称它为”常量指针”。
如何理解呢?如果说“指向常量”代表该指针指向的是一个“常量对象”,那么“常量指针”表示该指针本身的值是一个不变的常量。
建议习惯从右往左理解声明式的意义。例如double* const ptr = #
,从左往右,const ptr我们可知ptr本身是一个常量对象,而 *const ptr则表示ptr是一个“常量指针”,左侧的double表明了它所指对象的基础数据类型。
指针储存的值是什么呢?当然是所指对象的地址。所以,更具体的理解便是,“常量指针”声明时必须初始化并得到一个对象的地址,由于该指针本身的值,也就是所指对象的地址是不能改变的.
所以“常量指针”一旦指向了某个对象便必须永远指向它,类似下面的语句是非法的:
double num = 1.1;
double num2 = 1.2;
double* const ptr = #
ptr = &num2: // invalid!!!
考虑下面的声明兼定义式:
int m = 10;
const int* const pip = &m;
综合上面的叙述,相信这个表达式已经难不倒你了。
从右往左阅读,const pip表示pip是一个常量对象,int* const pip表示pip是一个int型的常量指针,再加上左侧的const表示pip指向“一个常量”。综合起来,就是pip是“指向常量的常量指针”。