a和*&a的区别

关于标题

这篇文章主要介绍const里面的一个现象。在这个现象里,a*&a是不同的,在大部分情况里,二者应该是一样的。

引入

今天在复习const各种用法时,看到了一篇文章,里面的现象令我不可思议。

我看到的博客

这里面有一段代码大概意思是这样的:

const int a = 1;
int* b = (int*)&a; 
// 先对a取地址,那就是一个const int*类型的指针,然后把他 强制类型转换 成int*类型的指针
*b = 2;
cout << a << endl;
cout << *b << endl;

请读者猜一下,a*b分别是什么?

大概可能会有读者认为*b = 2这一步会报错。

但实际上这句话可以正常运行,而且最后的输出是a = 1*b = 2

这里可能会有疑问,那就是ab地址是不是不一样啊?

于是检测一下:

cout << &a << endl;
cout<< b << endl;

结果表示两行输出的地址是一致的。

为什么从一样的地址取同样长度的内存,输出结果却不一样呢?下面进行简单介绍。

const int* 与 int*

在声明变量a的时候使用了const关键字,那就意味着这个变量a在程序执行过程中是不会变的。

那样的话,a就会在编译期进行赋值和使用。

然后既然a不变,那么说明a是个常量。那么编译器在编译期间会把a放入常量表里。(这一部分知识在编译原理这一块里。)

然后我们声明了一个指针b,使其指向a的地址。

正常情况下

int* b = &a;

是会报错的。因为bint*类型的指针而&a对应的是一个const int*类型的指针。
int*类型的指针是允许修改内存单元里的值的。
const int*类型就不允许。
所以出于安全性的考虑,上面这个代码跑不起来。

而如果在这里进行一个强制类型转换,即像文章开头那段代码一样加上(int*)(这个操作确实可行)
那样就能使得b指向a的地址且能通过b来修改a内存的值

所以上面的*b = 2不会报错。

为什么输出不一样?

那么问题就来了。已经通过指针b修改了a内存单元内的值,那为什么在cout << a;的时候仍会输出原来的1而不是修改后的2呢?

原因在于,编译器把a放入了常量表里,所以在cout << a;时会直接从常量表里寻找a而不是通过内存读取。

cout << *b就不一样了,因为b不是一个常量,所以需要在运行期间分配空间和赋值等,所以在cout << *b;时会老老实实从内存里去读取。

这就是两者不一样的原因。

如何解决?

如果希望修改后,cout << a;的结果是2,那应该如何操作?

这里我说一下,如果把一个变量声明为const类型,那就不要对其做修改。这是缺大德的行为!!!

我们继续。

如果希望每次读取变量的值时都从内存里老老实实读取的话,声明时要多加一个关键字volatile,形式如下。

const volatile int x = 10;
int* p = (int*)&x;
*p = 20;
cout << x << endl;
cout << *p << endl;

这回两行输出就都一样了。

回归标题

如果不加volatile还想实现修改后输出修改的值,那就可以cout << *&a << endl;

所以有时候这个操作并不一定是“多此一举”

总的来说,如果a是个const类型的,而且通过指针间接修改了a的值,那么a*&a会不一样。

希望大家以后永远不会遇到这些坑吧!嘿嘿嘿

感谢各位读者的阅读。如有错误或者补充欢迎十分感谢您在评论区留言。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值