指针常量与常量指针的翻译就好比机器学习中Regularization翻译成正则化一样,讲真,正则化这个说法确实要比规则化显得高端些,但是到了理解的时候,还是要按照规则化理解。
指针常量与常量指针这个概念是一样的,英文里没有pointer const这个词,只有pointer to const和const pointer这两个词。
而不管是指针常量还是常量指针他们的区别其实就是const关键字的位置,下面直接根据声明方式不同解释二者的区别: 在只有一个关键字const的情况下,声明有三种方式:
//1
const int* p;
//2
int const* p;
//3
int * const p;
复制
其中1和2是一种,这种情况下不能使用指针修改指向数据的值,但是也仅仅是不能使用指针p修改而已,p指向的值本身如果不是常量的话那么还可以直接对值修改,举个例子:
int a = 5;
const int* p = &a;
a = 4;//合法
*p = 3;//不合法
复制
由于这个特点,通常把const int* p
的形式作为函数的参量,以表示函数不会用这个指针修改数据,比如我们有一个子函数是想打印一个数组,那么我们可以将函数声明写成这样:
void printfarr(const int *arr,int n);
复制
如此,当主函数中调用该子函数,并打印主函数中的变量array的时候,永远不会出现array变化的情况,但是主函数自身想要修改array显然是可以的。所以被指向的数据的值到底能不能改变根本不由指针的声明方式决定,而是该数据本身是常量还是变量。
int a = 5;
const int b = 5;
const int* p = &a;
a = 4;//合法
*p = 3;//不合法
p = &b;//合法
b = 4;//不合法
*p = 3;//不合法
复制
而对于3,它的作用是保证指针不会指向别处,也就是一旦用这种方式声明并初始化,指针指向的地址永远不会发生变化,但是其中的值却可以通过指针改变:
int a = 5;
int b = 6;
int * const p = &a;
*p = 4;//合法
p = &b;//不合法
复制
以上就是所谓的指针常量与常量指针所包含的概念,在这里标个号: 1,2暂时称为第一类,3暂时称为第二类,那么第一类和第二类到底哪个叫做指针常量,那个叫做常量指针呢?说实话我都不知道指针常量与常量指针的叫法是不是够官方,我只能说概念非常混淆,而且其实它的两个名字并不重要,关键的是声明方式与作用的区别。
百度百科认为第一类应该叫做常量指针,第二类叫做指针常量
但是在《C Primer Plus》中将第一类叫做指向常量的指针,也就是在文章开头提到的pointer to const,那么第二类也就是const pointer了,但是这样一来,他就已经和百度百科的说法反了。
到目前为止我还没有找到更权威的说法,维基百科找不到这两个词,所以我们干脆不要去理会第一类与第二类到底该叫做什么名字,因为他们的声明方式与作用是决定清晰的就足够了。
上面说的情况,对于指针的修饰都只用了一个const关键字,还有两个const一起用的时候,此时的结果就是指针不能修改指向的数据,指针不能指向别的地方:
int a = 5;
int b = 6;
const int * const p = &a;//合法
*p = 4;//不合法
p = &b;//不合法
a = 7;//合法
复制
最后还有一个最严格的情况,就是数据本身就是常量,而且常量的地址不允许赋值给普通指针,这样一来数据自身不能改变,指针不能该数据,指针不能指向别处。
const int a = 5;
int b = 6;
int * const q = &a;//不合法
const int * const p = &a;//合法
*p = 4;//不合法
p = &b;//不合法
a = 7;//不合法