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 条评论
登录 后参与评论

相关文章

来自专栏Danny的专栏

正则表达式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

2232
来自专栏C/C++基础

C++接口继承与实现继承的区别和选择

《Effective C++》条款三十四:区分接口继承和实现继承中介绍的比较啰嗦,概括地说需要理解三点: (1)纯虚函数只提供接口继承,但可以被实现; ...

781
来自专栏LEo的网络日志

c库函数strncat出现乱字符

3897
来自专栏社区的朋友们

sizeof 知多少? (下)

稍熟悉 C/C++ 的朋友,对于 sizeof 肯定不陌生,通过它我们可以知晓某个类型或者实例的内存大小( 以字节计 ),网上关于这个话题的信息其实挺多的,但是...

1160
来自专栏梦魇小栈

重新介绍 JavaScript(JS全面系列教程)

为什么会有这一篇“重新介绍”呢?因为 JavaScript 堪称世界上被人误解最深的编程语言。虽然常被嘲为“玩具语言”,但在它看似简洁的外衣下,还隐藏着强大的语...

1752
来自专栏林德熙的博客

正则表达式30分钟入门教程

30分钟内让你明白正则表达式是什么,并对它有一些基本的了解,让你可以在自己的程序或网页里使用它。

550
来自专栏思考的代码世界

Python编程从入门到实践之使用列表|第3天

要创建切片,可指定要使用的第一个元素和最后一个元素的索引。与函数range()一样,Python 在到达你指定的第二个索引前面的元素后停止。要输出列表中的前三个...

3316
来自专栏java学习

java每日一练(2017/9/16)

本期题目 (单选题) 1、代码String str=”123456a”;int i=Integer.parseInt(str);会报异常的是() A java...

3818
来自专栏移动端开发

Swift 面向对象解析(二)

 接着上面一篇说的内容: 一 继承:      苹果继承与水果,苹果是水果的子类,则苹果是一种特殊的水果;这就是继承的关系,这个我们学OC的时候相信也都理解了...

2377
来自专栏前端知识分享

第158天:面向对象入门

在这里我们可以理解为创造对象的几种模式:单例模式,工厂模式,构造函数模式,原型模式等。

842

扫码关注云+社区

领取腾讯云代金券