C++ 指针常量与常量指针

吐槽一下: 指针常量与常量指针的翻译就好比机器学习中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;//不合法    

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏逆向技术

计算机基础知识_进制转化

          进制转化 一.任何一个进制转化为10进制的方式 156的十进制可以看做1*10^2 + 5*10^1  +   6*10^0 首先我们看一下...

1920
来自专栏服务端技术杂谈

Golang可变参数

既然我们知道了可变参数会被转换成切片,那么通过go语法糖,可以将一个存在的分配当作可变参数的参数。

773
来自专栏深度学习与计算机视觉

C++ 构造函数总结

C++提供了构造函数来处理对象的初始化。构造函数是一种特殊的成员函数,与其他成员函数不同,构造函数不需要用户来调用它,而是建立对象时自动执行。 构造函数的名...

2016
来自专栏null的专栏

python——时间与时间戳之间的转换

对于时间数据,如2016-05-05 20:28:54,有时需要与时间戳进行相互的运算,此时就需要对两种形式进行转换,在Python中,转换时需要用到time模...

3198
来自专栏前端之路

字符串、数组处理方法总结

933
来自专栏Python小屋

Python内置函数max()高级用法

不管是排序还是选取最大值或者最小值,都应该有个规则或者顺序,而平时我们所说的最大值或最小值实际上也是在某种排序规则或顺序下的最大值和最小值。Python内置函数...

2464
来自专栏微信公众号:Java团长

3张图彻底了解Java中字符串的不变性

一旦一个string对象在内存(堆)中被创建出来,他就无法被修改。特别要注意的是,String类的所有方法都没有改变字符串本身的值,都是返回了一个新的对象。

462
来自专栏idba

*args 和 **kwargs的用法

一 简介 *args 和 **kwargs 主要用于函数定义。 当我们需要定义的函数的传入参数个数不确定时,可以使用*args 和 **kwargs ...

623
来自专栏十月梦想

流程控制的另一种书写方式

多个层次的嵌套会有多个括号看起来比较繁琐,流程控制可以用:代表左侧的{;endif、endswitch、endfor、endwhile、endforeach代表...

717
来自专栏null的专栏

PHP基础——PHP数组

PHP数组与其他语言的数组有些不同,在PHP中,数组包含两种类型的数组: 数字索引数组 关联数组 其中,数字索引数组是指其key为数字,而后者可以使用字符串作为...

3276

扫码关注云+社区