免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: dingning239
打印 上一主题 下一主题

此题何解?求高人指点 [复制链接]

论坛徽章:
0
41 [报告]
发表于 2011-03-22 09:07 |只看该作者
j = (((++i) + (--i)) - (--i));

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
42 [报告]
发表于 2011-03-22 09:18 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
43 [报告]
发表于 2011-03-22 14:24 |只看该作者
用gdb调试跟踪不错来吗?

论坛徽章:
0
44 [报告]
发表于 2011-03-22 15:30 |只看该作者
回复 1# dingning239


你这问题真是对不起你的头像啊,还搞得很求是一样,自己错了就承认,不要再这么折腾下去了,没意思

论坛徽章:
0
45 [报告]
发表于 2011-03-22 16:20 |只看该作者
  1.   1     .file   "m.c"
  2.   2     .section    .rodata
  3.   3 .LC0:
  4.   4     .string "j is :%d,i is :%d\n"
  5.   5     .text
  6.   6 .globl main
  7.   7     .type   main, @function
  8.   8 main:
  9.   9     pushl   %ebp
  10. 10     movl    %esp, %ebp
  11. 11     andl    $-16, %esp
  12. 12     subl    $32, %esp
  13. 13     movl    $5, 28(%esp)
  14. 14     addl    $1, 28(%esp)
  15. 15     subl    $1, 28(%esp)
  16. 16     movl    28(%esp), %eax
  17. 17     addl    %eax, %eax
  18. 18     subl    $1, 28(%esp)
  19. 19     subl    28(%esp), %eax
  20. 20     movl    %eax, 24(%esp)
  21. 21     movl    $.LC0, %eax
  22. 22     movl    28(%esp), %edx
  23. 23     movl    %edx, 8(%esp)
  24. 24     movl    24(%esp), %edx
  25. 25     movl    %edx, 4(%esp)
  26. 26     movl    %eax, (%esp)
  27. 27     call    printf
  28. 28     call    getchar
  29. 29     leave
  30. 30     ret
  31. 31     .size   main, .-main


  32.   1 #include <stdio.h>
  33.   2
  34.   3 int main ()
  35.   4 {
  36.   5
  37.   6     int j,i = 5;
  38.   7     j = (++i)+(--i)-(--i);
  39.   8     printf("j is :%d,i is :%d\n",j, i);
  40.   9     getchar();
  41. 10 }
  42. ~                  
  43. 汇编代码分析:
  44.   13     movl    $5, 28(%esp)   ==》 i = 5; 这里的28(%esp)就是堆栈偏移28,也就是局部变量i
  45.   14     addl    $1, 28(%esp)   ==>  ++i;
  46.   15     subl    $1, 28(%esp)   ==>  --i;
  47.   到这里i的结果是5,也是符合我们预期的。
  48.   接下来就不是我们想看到的,
  49.   16     movl    28(%esp), %eax
  50.   17     addl    %eax, %eax     
  51.   gcc编译器,把++i 和 --i的结果都放在堆栈28(%esp)同一个位置上,
  52.   代码17行,就相当于 5+5 ==》10, 我们预期的是11
  53.   然后subl    $1, 28(%esp),再减1, ==》 i==4
  54.   那得到 j = 10 - 4, 当然结果就是6啦。

  55.   所以说不要在同一个点上改变一个变量两次及以上,不然会得到你不想要的结果。
  56.   声明:本人汇编不熟悉,临时看了下汇编语法分析的,有不对的地方,请指出。
  57.   
  58.   
  59.   
  60.   
  61.   
  62.   可以参考下面的代码看:
  63.   下面的运行结果符合我们期望,因为 变量a、b、c 分别对应堆栈  60(%esp) 56(%esp) 52(%esp)
  64.   这样计算结果不会互相干扰。得到的结果就是 6+5-4 == 7

  65.   1     .file   "mm.c"
  66.   2     .section    .rodata
  67.   3     .align 4
  68.   4 .LC0:
  69.   5     .string "a is :%d,b is :%d, c is:%d, d is %d\n"
  70.   6     .text
  71.   7 .globl main
  72.   8     .type   main, @function
  73.   9 main:
  74. 10     pushl   %ebp
  75. 11     movl    %esp, %ebp
  76. 12     andl    $-16, %esp
  77. 13     subl    $64, %esp
  78. 14     movl    $5, 60(%esp)
  79. 15     addl    $1, 60(%esp)
  80. 16     movl    60(%esp), %eax
  81. 17     movl    %eax, 56(%esp)
  82. 18     subl    $1, 60(%esp)
  83. 19     movl    60(%esp), %eax
  84. 20     movl    %eax, 52(%esp)
  85. 21     subl    $1, 60(%esp)
  86. 22     movl    60(%esp), %eax
  87. 23     movl    %eax, 48(%esp)
  88. 24     movl    52(%esp), %eax
  89. 25     movl    56(%esp), %edx
  90. 26     leal    (%edx,%eax), %eax
  91. 27     subl    48(%esp), %eax
  92. 28     movl    %eax, 44(%esp)
  93. 29     movl    $.LC0, %eax
  94. 30     movl    44(%esp), %edx
  95. 31     movl    %edx, 16(%esp)
  96. 32     movl    48(%esp), %edx
  97. 33     movl    %edx, 12(%esp)
  98. 34     movl    52(%esp), %edx
  99. 35     movl    %edx, 8(%esp)
  100. 36     movl    56(%esp), %edx
  101. 37     movl    %edx, 4(%esp)
  102. 38     movl    %eax, (%esp)
  103. 39     call    printf


  104.   1 #include <stdio.h>
  105.   2
  106.   3 int main ()
  107.   4 {
  108.   5
  109.   6     int j,i = 5;
  110.   7     int a = ++i;
  111.   8     int b = --i;
  112.   9     int c = --i;
  113. 10     int d = a + b - c;
  114. 11     printf("a is :%d,b is :%d, c is:%d, d is %d\n", a, b, c, d );
  115. 12     //j = (++i)+(--i)-(--i);
  116. 13     //printf("j is :%d,i is :%d\n",j, i);
  117. 14     getchar();
  118. 15 }
复制代码

论坛徽章:
0
46 [报告]
发表于 2011-03-22 16:21 |只看该作者
回复  dingning239


你这问题真是对不起你的头像啊,还搞得很求是一样,自己错了就承认,不要再这么折 ...
churchmice 发表于 2011-03-22 15:30



    拜托,废话别在这里说!!!!!

论坛徽章:
0
47 [报告]
发表于 2011-03-22 16:28 |只看该作者
回复 45# hebingyue


    多谢你的指点,这样的分析是我要的结果,不像其他说空话、废话的人!

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
48 [报告]
发表于 2011-03-22 16:29 |只看该作者
拜托,废话别在这里说!!!!!
dingning239 发表于 2011-03-22 16:21



    为了一个不同编译器解释不一样的行为去深究,你觉得有必要吗?什么叫未定义行为,也就是如果你运行这个导致硬盘废掉,也丝毫不违背C语言标准的规定.
   真要想知道为什么会这样,那么你把你编译链接出来的执行程序反编译一下看看不就行了

论坛徽章:
0
49 [报告]
发表于 2011-03-22 16:33 |只看该作者
楼上的,你说的对我来说没有一点用,这个帖子到此结贴!

感谢pmerofc hebingyue  egmkang 三位的回答!

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
50 [报告]
发表于 2011-03-22 16:38 |只看该作者
楼上的,你说的对我来说没有一点用,这个帖子到此结贴!

感谢pmerofc hebingyue  egmkang 三位的回答!
dingning239 发表于 2011-03-22 16:33



    没有一点用?
   "你把你编译链接出来的执行程序反编译一下看看不就行了"
  这几个字看清楚了吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP