中易网

c++通过强制转换修改常量的值

答案:5  悬赏:40  
解决时间 2021-01-13 19:49
  • 提问者网友:趣果有间
  • 2021-01-13 05:49
c++通过强制转换修改常量的值
最佳答案
  • 二级知识专家网友:风格不统一
  • 2021-01-13 06:10
在C/C++中,通过强制转换修改常量值,从代码上是可以做到的。但是最好不要这样做。
原理:
在C/C++中,任意的指针的本质,都是地址。而在指针之间,通过强制转换,是允许把一种指针转换成另一种指针的。在这个指针转换的过程中,就可以强制的把常量属性(const)取消掉。从而实现修改常量的目的。
示例:
const int a=10;
*(int *)&a = 100;解析:

先取a的地址,这是一个const int *的指针。
然后将其转换为int *类型,这步操作是语法上允许的。
最后用*取值,并赋值成新的值。
缺陷:
带来不可预知的危险。

如果常量本身在定义初期,就是一个常量类型,那么会被分配到系统常量区存储,这是一个只读的空间,任何写操作,都会引起程序崩溃。如之前示例中的程序,只是绕过了编译的报错,执行的时候还是会出问题的。
如果常量只是一个普通的变量,在特殊情况下,如函数参数传递,被赋予了常量属性,那么这种修改不会引起问题。但是,作为面向对象语言,被封装的一个函数无法预知传入的参数是普通变量增加了常量属性还是本身就是一个常量,所以这样强制的转换赋值常量,在实际编程中是不允许使用的。
全部回答
  • 1楼网友:傲气稳了全场
  • 2021-01-13 09:58

赞同楼下的观点,是因为编译器做了某种优化导致的,直接简单粗暴的当成宏一样替换导致的,实际上是修改到了const变量的值了的,下面的代码可以说明
#include 
#include 
void test(const int& m)
{
printf("m=%d ",m);
}
int main()
{
const int n=0;
int* p=(int*)(&n);
*p=2;
int* p2=(int*)(&n);
printf("*p=%d n=%d *p2=%d ",*p,n,*p2);
test(n);
printf("*p=%d n=%d *p2=%d ",*p,n,*p2);
return 0;
}
输出结果为*p=2 n=0 *p2=2
m=2
*p=2 n=0 *p2=2
  • 2楼网友:迷人又混蛋
  • 2021-01-13 08:29
因为aa变量已被设置为只读变量,所以你在编译执行时编译器会选择原来的23,若将const修饰符去掉,则可得到你想要得结果!追问但是我通过单步调试看到运行了 *p=66; 之后,aa的值 已经变成66了,结果输出的还是原来 的.追答在原理上aa的值应该是66了但编译器在看到该变量前面的const修饰符后,便不会去更改其值!而是保持它原有的值,这个就是编译器中的只读变量,它只读不可修改!相反还有个volatile修饰符,它是可变的即编译器会很小心的去看待这个变量!
  • 3楼网友:爱难随人意
  • 2021-01-13 08:23
因为编译器的处理(或者说“优化”),把两处aa看成两个不同的变量(或者看成真正的常量)以简化操作,加快运行速度。遇到这种BUG建议换一个编译器进行测试……
  • 4楼网友:鱼芗
  • 2021-01-13 07:30
你看到的东西没错,
原aa的内容的确被改变了,
但是当编译器调用cout的时候,
入栈的参数是常量23,不是aa变量。
这点从反汇编一眼就能看出。
你只要看到push 17h就知道我说的没错了。
如果加上这段代码你就知道确实已经改了
cout< int x=aa;
cout<这样输出还是23,66,23,
看来是编译就是这个死脑筋,只要引用到常量的地方都会用最原始的常量本身去替换。
aa只不过是个常量名字而已,实际用到aa的值(而不是地址)的地方都是直接用值本身(23)去替换的,这个应该是没办法的。
而实际上这个变量的所在地址的内容已经被替换成功了,换句话说,编译器是从来不考虑这个常量从地址被修改的情况的,一开始定义成什么就永远是什么了,不会被重新从地址取值的。
我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息!
大家都在看
推荐信息