LukaDoncicY77 发表于 2021-10-20 21:32:33

关于devc++和vc6.0自加运算符结果不同的原因

#include <stdio.h>
int main()
{
        int i=3,j=3,x,y;
        x=(i++)+(i++)+(i++);
        y=(++j)+(++j)+(++j);
        printf("%d\t%d\t",x,y);
        printf("%d\t%d\t",i,j);
        return 0;
}
通过DevC++ 的运算结果为12 16 6 6
通过VC6.0的运算结果为9 16 6 6
想知道为什么 二者结果不同- -       
https://www.wenmi.com/article/q02a4w03yqga.html
这里有一个相关内容的链接 但是没有讲述上述这种情况,所以来此求助

hrpzcf 发表于 2021-10-21 11:35:40

编译器的原因吧,各编译器实现方法不同,编译结果也不同,所以建议不要用这种写法。

我试了下
用gcc编译结果是12 16 6 6
用calng 编译结果是 12 15 6 6,并且有警告。这里的y=15才是预期结果。
PS F:\Repos\ccode> clang main.c -o main.exe
main.c:6:11: warning: multiple unsequenced modifications to 'i' [-Wunsequenced]
    x = (i++) + (i++) + (i++);
          ^       ~~
main.c:7:10: warning: multiple unsequenced modifications to 'j' [-Wunsequenced]
    y = (++j) + (++j) + (++j);
         ^       ~~
2 warnings generated.
PS F:\Repos\ccode> ./main
12      15      6       6
PS F:\Repos\ccode>

jackz007 发表于 2021-10-21 11:55:33

本帖最后由 jackz007 于 2021-10-21 12:28 编辑

      我分别使用 vc6.0 和 gcc 10.2.0 编译了这个源程序,并使用 OllyDBG 仔细跟踪了两个程序的反汇编代码,把算法过程用 C 语言进行了描述,可以看出,两个编译器产生代码的主要差异在于计算 x 过程的完全不同,计算 y 的过程二者完全相同。
#include <stdio.h>

void vc(void)
{
      int i = 3 , j = 3 , x , y ;
      x = i + i + i             ;
      i ++                      ;
      i ++                      ;
      i ++                      ;
      j ++                      ;
      j ++                      ;
      y = j + j               ;
      j ++                      ;
      y += j                  ;
      printf("%d\t%d\t",x,y)    ;
      printf("%d\t%d\n",i,j)    ;
}

void gcc()
{
      int i = 3 , j = 3 , x , y ;
      x = i                     ;
      i ++                      ;
      x += i                  ;
      i ++                      ;
      x += i                  ;
      i ++                      ;
      j ++                      ;
      j ++                      ;
      y = j + j               ;
      j ++                      ;
      y += j                  ;
      printf("%d\t%d\t",x,y)    ;
      printf("%d\t%d\n",i,j)    ;
}

int main(void)
{
      printf("-------- vc6.0 --------\n") ;
      vc()                              ;
      printf("-------- dev-c --------\n") ;
      gcc()                               ;
}
      编译、运行实况
D:\0002.Exercise\C>g++ -o x x.c

D:\0002.Exercise\C>x
-------- vc6.0 --------
9       16      6       6
-------- dev-c --------
12      16      6       6

D:\0002.Exercise\C>

jackz007 发表于 2021-10-21 15:03:00

本帖最后由 jackz007 于 2021-10-21 20:23 编辑

      相关反汇编代码分析
====================================================================================================================================================
*                                                               vc6.0 - 编译                                                                     *
====================================================================================================================================================
00401000/$55                         push    ebp
00401001|.8BEC                     mov   ebp, esp
00401003|.83EC 10                  sub   esp, 0x10
00401006|.C745 F4 03000000         mov   dword ptr , 0x3                                 ;i = 3
0040100D|.C745 F0 03000000         mov   dword ptr , 0x3                                  ;j = 3
00401014|.8B45 F4                  mov   eax, dword ptr                                  ;x = i
00401017|.0345 F4                  add   eax, dword ptr                                  ;x = x + i
0040101A|.0345 F4                  add   eax, dword ptr                                  ;x = x + i
0040101D|.8945 FC                  mov   dword ptr , eax
00401020|.8B4D F4                  mov   ecx, dword ptr
00401023|.83C1 01                  add   ecx, 0x1
00401026|.894D F4                  mov   dword ptr , ecx                                 ;i = i + 1
00401029|.8B55 F4                  mov   edx, dword ptr
0040102C|.83C2 01                  add   edx, 0x1
0040102F|.8955 F4                  mov   dword ptr , edx                                 ;i = i + 1
00401032|.8B45 F4                  mov   eax, dword ptr
00401035|.83C0 01                  add   eax, 0x1
00401038|.8945 F4                  mov   dword ptr , eax                                 ;i = i + 1
0040103B|.8B4D F0                  mov   ecx, dword ptr
0040103E|.83C1 01                  add   ecx, 0x1
00401041|.894D F0                  mov   dword ptr , ecx                                  ;j = j + 1
00401044|.8B55 F0                  mov   edx, dword ptr
00401047|.83C2 01                  add   edx, 0x1
0040104A|.8955 F0                  mov   dword ptr , edx                                  ;j = j + 1
0040104D|.8B45 F0                  mov   eax, dword ptr                                   ;y = j
00401050|.0345 F0                  add   eax, dword ptr                                   ;y = y + j
00401053|.8B4D F0                  mov   ecx, dword ptr
00401056|.83C1 01                  add   ecx, 0x1
00401059|.894D F0                  mov   dword ptr , ecx                                  ;j = j + 1
0040105C|.0345 F0                  add   eax, dword ptr                                   ;y = y + j
0040105F|.8945 F8                  mov   dword ptr , eax
00401062|.8B55 F8                  mov   edx, dword ptr
00401065|.52                         push    edx
00401066|.8B45 FC                  mov   eax, dword ptr
00401069|.50                         push    eax
0040106A|.68 30704000                push    00407030                                                   ;ASCII "%d\t%d\t"
0040106F|.E8 1E000000                call    00401092
00401074|.83C4 0C                  add   esp, 0xC
00401077|.8B4D F0                  mov   ecx, dword ptr
0040107A|.51                         push    ecx
0040107B|.8B55 F4                  mov   edx, dword ptr
0040107E|.52                         push    edx
0040107F|.68 38704000                push    00407038                                                   ;ASCII "%d\t%d\t"
00401084|.E8 09000000                call    00401092
00401089|.83C4 0C                  add   esp, 0xC
0040108C|.33C0                     xor   eax, eax
0040108E|.8BE5                     mov   esp, ebp
00401090|.5D                         pop   ebp
00401091\.C3                         retn
====================================================================================================================================================
====================================================================================================================================================
*                                                            gcc 10.2.0 - 编译                                                                     *
====================================================================================================================================================
00401500/$55                         push    ebp
00401501|.89E5                     mov   ebp, esp
00401503|.83E4 F0                  and   esp, 0xFFFFFFF0
00401506|.83EC 20                  sub   esp, 0x20
00401509|.E8 02020000                call    00401710
0040150E|.C74424 1C 03000000         mov   dword ptr , 0x3                                  ; ||i = 3
00401516|.C74424 18 03000000         mov   dword ptr , 0x3                                  ; ||j = 3
0040151E|.8B5424 1C                  mov   edx, dword ptr                                   ; ||v1 = i
00401522|.8D42 01                  lea   eax, dword ptr                                  ; ||
00401525|.894424 1C                  mov   dword ptr , eax                                  ; ||i = i + 1
00401529|.8B4424 1C                  mov   eax, dword ptr                                   ; ||v2 = i
0040152D|.8D48 01                  lea   ecx, dword ptr                                  ; ||
00401530|.894C24 1C                  mov   dword ptr , ecx                                  ; ||i = i + 1
00401534|.8D0C02                     lea   ecx, dword ptr                                  ; ||x = v1 + v2
00401537|.8B4424 1C                  mov   eax, dword ptr                                   ; ||v3 = i
0040153B|.8D50 01                  lea   edx, dword ptr                                  ; ||
0040153E|.895424 1C                  mov   dword ptr , edx                                  ; ||i = i + 1
00401542|.01C8                     add   eax, ecx                                                   ; ||x = x + v3
00401544|.894424 14                  mov   dword ptr , eax                                  ; ||
00401548|.834424 18 01               add   dword ptr , 0x1                                  ; ||j = j + 1
0040154D|.834424 18 01               add   dword ptr , 0x1                                  ; ||j = j + 1
00401552|.8B4424 18                  mov   eax, dword ptr                                   ; ||y = j
00401556|.8D1400                     lea   edx, dword ptr                                  ; ||y = y + j
00401559|.834424 18 01               add   dword ptr , 0x1                                  ; ||j = j + 1
0040155E|.8B4424 18                  mov   eax, dword ptr                                   ; ||
00401562|.01D0                     add   eax, edx                                                   ; ||y = y + j
00401564|.894424 10                  mov   dword ptr , eax                                  ; ||
00401568|.8B4424 10                  mov   eax, dword ptr                                   ; ||
0040156C|.894424 08                  mov   dword ptr , eax                                 ; ||
00401570|.8B4424 14                  mov   eax, dword ptr                                   ; ||
00401574|.894424 04                  mov   dword ptr , eax                                 ; ||
00401578|.C70424 00404000            mov   dword ptr , 00404000                                  ; ||ASCII "%d\t%d\t"
0040157F|.E8 60110000                call    <jmp.&msvcrt.printf>                                       ; |\printf
00401584|.8B4424 18                  mov   eax, dword ptr                                   ; |
00401588|.894424 08                  mov   dword ptr , eax                                 ; |
0040158C|.8B4424 1C                  mov   eax, dword ptr                                   ; |
00401590|.894424 04                  mov   dword ptr , eax                                 ; |
00401594|.C70424 00404000            mov   dword ptr , 00404000                                  ; |ASCII "%d\t%d\t"
0040159B|.E8 44110000                call    <jmp.&msvcrt.printf>                                       ; \printf
004015A0|.B8 00000000                mov   eax, 0x0
004015A5|.C9                         leave
004015A6\.C3                         retn
====================================================================================================================================================

LukaDoncicY77 发表于 2021-10-21 21:46:53

hrpzcf 发表于 2021-10-21 11:35
编译器的原因吧,各编译器实现方法不同,编译结果也不同,所以建议不要用这种写法。

我试了下


感谢帮助

LukaDoncicY77 发表于 2021-10-21 23:16:03

jackz007 发表于 2021-10-21 11:55
我分别使用 vc6.0 和 gcc 10.2.0 编译了这个源程序,并使用 OllyDBG 仔细跟踪了两个程序的反汇编代 ...

感谢帮助
页: [1]
查看完整版本: 关于devc++和vc6.0自加运算符结果不同的原因