免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2166 | 回复: 4

[C++] const_cast转换的问题 [复制链接]

论坛徽章:
0
发表于 2014-08-29 12:12 |显示全部楼层
本帖最后由 bjutslg 于 2014-08-29 12:28 编辑
  1.         const int s=10;
  2.         int *p=const_cast<int*>(&s);
  3.         *p=11;
  4.         cout<<p<<" "<<&s<<endl;
  5.         cout<<*p<<" "<<s<<endl;
复制代码
这样的话 地址是一样的 为什么内容不一样呢

为什么这样有可以改变值
  1.          
  2.         const int*  a=&v;
  3.         int *b=const_cast<int*>(a);         
  4.         cout<<*a<<endl;
  5.         *b=11;
  6.         cout<<*a<<endl;
复制代码

论坛徽章:
0
发表于 2014-08-29 13:28 |显示全部楼层
本帖最后由 jwj070524 于 2014-08-29 13:29 编辑
  1. #include <stdio.h>

  2. int main ()
  3. {
  4.   int const v = 0;

  5.   int *ptr = const_cast<int*>(&v);

  6.   *ptr = 1;

  7.   printf("v = %d, *ptr = %d\n", v, *ptr);
  8. }
复制代码
转换成汇编后:
  1. main:
  2. .LFB2:
  3.         leal    4(%esp), %ecx
  4. .LCFI0:
  5.         andl    $-16, %esp
  6.         pushl   -4(%ecx)
  7. .LCFI1:
  8.         pushl   %ebp
  9. .LCFI2:
  10.         movl    %esp, %ebp        ; v   => [ebp-12]
  11. .LCFI3:                           ; ptr => [ebp-8]
  12.         pushl   %ecx
  13. .LCFI4:
  14.         subl    $36, %esp
  15. .LCFI5:
  16.         movl    $0, -12(%ebp)     ; [ebp-12] := 0         ;int const v = 0;
  17.         leal    -12(%ebp), %eax   ; eax      := ebp-12    ;eax = &v
  18.         movl    %eax, -8(%ebp)    ; [ebp-8]  := ebp-12    ;ptr = &v
  19.         movl    -8(%ebp), %eax    ; eax      := [ebp-8]   ;eax = v
  20.         movl    $1, (%eax)        ; eax      := 1         ;eax = 1
  21.         movl    -8(%ebp), %eax    ; eax      := [ebp-8]   ;eax = &v
  22.         movl    (%eax), %eax      ; eax      := [[ebp-8]] ;eax = v
  23.         movl    %eax, 8(%esp)     ; [esp+8]  := [[ebp-8]] ;store (*ptr)
  24.         movl    $0, 4(%esp)       ; [esp+4]  := 0         ;store (v) == 0 由于v是常量,直接赋0
  25.         movl    $.LC0, (%esp)     ; [esp]    :=           ;store (char const *)
  26.         call    printf
复制代码

论坛徽章:
0
发表于 2014-08-29 14:05 |显示全部楼层
看不很懂啊回复 2# jwj070524


   

论坛徽章:
1
处女座
日期:2014-09-18 16:18:00
发表于 2014-08-29 14:58 |显示全部楼层
本帖最后由 Kasiotao 于 2014-08-29 15:02 编辑

回复 1# bjutslg
你可以用强制类型转换在gcc下编译一下,结果可以改变原const变量的值,在c语言中是允许这样
但是同样的程序在C++中你就修改不了,貌似在C++中修改const变量的值是未定义的行为,这一点C++ primer上明确说了

   

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
发表于 2014-08-29 15:22 |显示全部楼层
你的代码逻辑是错误的,因为 &s 不可以被当成 int* 看待

打个比方,
甲有一个可刻录光盘(int*)
乙向甲索要一个只读光盘(const int*),甲给了乙一个可刻录光盘(int*)【int* 可以隐式转化为const int*的原因不需要我解释了吧?!】
丙从乙处得到这个“被乙认为是只读光盘”的光盘,但丙知道这个光盘其实是可刻录光盘,于是丙将光盘放进刻录机刻录一段AV。
故事结束,毫无违和感吧:)

而你的问题在于,将一个本不是“可刻录光盘”的光盘当成“可刻录光盘”来刻录,自然其结果是“未定义”的。

对于『未定义行为』,根本就无法去解释其执行过程,看反汇编也没屌用,不要混淆了『未定义行为』和『实现定义行为』的差别。(给个忠告,永远不要用反汇编来解释C++,因为汇编是根据C++标准生成的,而C++标准是不受编译器反馈影响的)
如果你一定对结果要个解释的话,我只能说大部分『未定义行为』是留给编译器作优化的
对于
const int s=10;
……
*p=11;
cout<<*p<<" "<<s<<endl;
因为 *p=11 到输出 *p 之间没有任何修改*p和p的行为,所以 *p 值自然还是11
对于 const int s=10,因为 s 是不可修改的,所以 s 值自然还是10
整段代码其实被优化成 cout << 11 << 10 << endl,假如你用的编译器足够优秀的话。
当然,你可能会说你强制修改了s呀?但,编译器可不管,因为C++标准没要求编译器来管你这未定义的行为,C++只对有定义行为的代码负责任。也就是说编译器不单可以输出 11,10 和 11,11 这些你能猜出的结果,也可能直接删除你的chinaunix帐号,为什么?因为这就是“未定义行为”嘛!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP