首页
社区
课程
招聘
[讨论]不同平台编译对连加等式结果不同
发表于: 2013-9-6 17:54 4963

[讨论]不同平台编译对连加等式结果不同

2013-9-6 17:54
4963
#include <STDIO.H>

int main(int argc, char* argv[])
{

         int a = 0;
          a = a + (a++)+(++a);
          int b = 0;
          b = (++b) + b + (b++);
          int c  = 0;
          c = (c++) + c + (++c);
          printf("a = %d b = %d c = %d",a,b,c);
        getchar();
        return 0;
}
这份代码在win7 X64系统里面 打印的结果 a= 4 b =4 c = 4
而在 其他 32位平台打印的都是 a = 2 b = 4 c = 2

记得以前有人问过我一个问题,是几个变量进行加运算然后Debug和 release版本运行起来结果不同,但是时间太久了,记不清了所以打算自己写写试试能不能找到这样的例子,但是在我的WIN 7 X64位机器上上面的例子竟然打印的全是4

而我期待的结果是 2 4 2
然后再win32和linux 32位上都是 2 4 2

鉴于这样的结果于是进入汇编层调试,看看编译器是怎么编译生成的二级制代码的
我的64位机器上的编译的结果如下
三种顺序加法都是一样的先计算++a 然后 计算三个数相加 然后计算 a++
编译器相同的但是就是因为一个电脑是64位的一个是32位的就出现不同的结果
在汇编级别进行调试发现了问题
32位 的反汇编

.text:00401028                 mov     [ebp+var_4], 0  ; a = 0
.text:0040102F                 mov     eax, [ebp+var_4] ; 取出a 然后计算 a+(a++)
.text:00401032                 add     eax, [ebp+var_4] ; a+(a++) 也就是 a+a
.text:00401035                 mov     ecx, [ebp+var_4] ; 此时写回 a的值为0
.text:00401038                 add     ecx, 1          ; 在进行+(++a)操作之前先进行 ++a操作
.text:0040103B                 mov     [ebp+var_4], ecx ; 此时写回 a的值为1
.text:0040103E                 add     eax, [ebp+var_4] ; 把++a之后的a值和 a+(a++)进行加 0+1
.text:00401041                 mov     [ebp+var_4], eax ; 此时写回 a的值为1
.text:00401044                 mov     edx, [ebp+var_4]
.text:00401047                 add     edx, 1          ; 最后进行a++操作 1++ =2
.text:0040104A                 mov     [ebp+var_4], edx
.text:0040104D                 mov     [ebp+var_8], 0  ; b = 0
.text:00401054                 mov     eax, [ebp+var_8] ; 计算 ++b
.text:00401057                 add     eax, 1
.text:0040105A                 mov     [ebp+var_8], eax ; b =1
.text:0040105D                 mov     ecx, [ebp+var_8]
.text:00401060                 add     ecx, [ebp+var_8] ; (++b)+b  1+1 = 2
.text:00401063                 add     ecx, [ebp+var_8] ; {(++b)+b}+(b++)  {2}+1=3 也就是之前的结果再加上一个b
.text:00401066                 mov     [ebp+var_8], ecx ; 因为b++ 是先使用再进行++操作
.text:00401069                 mov     edx, [ebp+var_8]
.text:0040106C                 add     edx, 1          ; 最后计算b++ 3+1 =4
.text:0040106F                 mov     [ebp+var_8], edx
.text:00401072                 mov     [ebp+var_C], 0  ; c = 0
.text:00401079                 mov     eax, [ebp+var_C]
.text:0040107C                 add     eax, [ebp+var_C] ; (c++)+c 0+0 =0
.text:0040107F                 mov     ecx, [ebp+var_C] ; 计算 ++c
.text:00401082                 add     ecx, 1
.text:00401085                 mov     [ebp+var_C], ecx ; ++c 计算之后 c的值为1
.text:00401088                 add     eax, [ebp+var_C] ; 计算 {(c++)+c}+(++c)也就是0+1 =1
.text:0040108B                 mov     [ebp+var_C], eax
.text:0040108E                 mov     edx, [ebp+var_C] ; 最后计算 c++ c=2
.text:00401091                 add     edx, 1
.text:00401094                 mov     [ebp+var_C], edx
.text:00401097                 mov     eax, [ebp+var_C]
.text:0040109A                 push    eax
.text:0040109B                 mov     ecx, [ebp+var_8]
.text:0040109E                 push    ecx
.text:0040109F                 mov     edx, [ebp+var_4]
.text:004010A2                 push    edx
.text:004010A3                 push    offset Format   ; "a = %d b = %d c = %d"
.text:004010A8                 call    _printf
我的64位 编译生成的结果却并不同
.text:0040102E                 mov     [ebp+a], 0
.text:00401035                 mov     eax, [ebp+a]
.text:00401038                 add     eax, 1
.text:0040103B                 mov     [ebp+a], eax
.text:0040103E                 mov     ecx, [ebp+a]
.text:00401041                 add     ecx, [ebp+a]
.text:00401044                 add     ecx, [ebp+a]
.text:00401047                 mov     [ebp+a], ecx
.text:0040104A                 mov     edx, [ebp+a]
.text:0040104D                 add     edx, 1
.text:00401050                 mov     [ebp+a], edx
.text:00401053                 mov     [ebp+b], 0
.text:0040105A                 mov     eax, [ebp+b]
.text:0040105D                 add     eax, 1
.text:00401060                 mov     [ebp+b], eax
.text:00401063                 mov     ecx, [ebp+b]
.text:00401066                 add     ecx, [ebp+b]
.text:00401069                 add     ecx, [ebp+b]
.text:0040106C                 mov     [ebp+b], ecx
.text:0040106F                 mov     edx, [ebp+b]
.text:00401072                 add     edx, 1
.text:00401075                 mov     [ebp+b], edx
.text:00401078                 mov     [ebp+c], 0
.text:0040107F                 mov     eax, [ebp+c]
.text:00401082                 add     eax, 1
.text:00401085                 mov     [ebp+c], eax
.text:00401088                 mov     ecx, [ebp+c]
.text:0040108B                 add     ecx, [ebp+c]
.text:0040108E                 add     ecx, [ebp+c]
.text:00401091                 mov     [ebp+c], ecx
.text:00401094                 mov     edx, [ebp+c]
.text:00401097                 add     edx, 1
.text:0040109A                 mov     [ebp+c], edx
.text:0040109D                 mov     eax, [ebp+c]
.text:004010A0                 push    eax
.text:004010A1                 mov     ecx, [ebp+b]
.text:004010A4                 push    ecx
.text:004010A5                 mov     edx, [ebp+a]
.text:004010A8                 push    edx
.text:004010A9                 push    offset format   ; "a = %d b = %d c = %d"
.text:004010AE                 call    _printf

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 113
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
http://bbs.csdn.net/topics/370153775
2013-9-6 19:06
0
雪    币: 114
活跃值: (180)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
又见这个问题...
2013-9-6 19:07
0
雪    币: 238
活跃值: (55)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
4
嗯,学习了,原来不想才是对的,果然我没去细抠是正确的
2013-9-6 19:25
0
雪    币: 623
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
都老会员了,还不知什么叫“未定义行为”吗?
这种问题,只有刚学 C 的人才会问的。
2013-9-6 19:42
0
雪    币: 275
活跃值: (51)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
老会员跟这个问题有什么关系?
都成人了,说话不能只针对问题本身吗?
2013-9-6 19:59
0
雪    币: 275
活跃值: (51)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
世界上没有愚蠢和不值得问的问题,只有喜欢冒充高手的自以为是者
2013-9-6 20:01
0
雪    币: 623
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
8
你激动啥
好,你继续研究,别停
2013-9-6 20:49
0
游客
登录 | 注册 方可回帖
返回
//