关于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
这里有一个相关内容的链接 但是没有讲述上述这种情况,所以来此求助 编译器的原因吧,各编译器实现方法不同,编译结果也不同,所以建议不要用这种写法。
我试了下
用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 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 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
==================================================================================================================================================== hrpzcf 发表于 2021-10-21 11:35
编译器的原因吧,各编译器实现方法不同,编译结果也不同,所以建议不要用这种写法。
我试了下
感谢帮助 jackz007 发表于 2021-10-21 11:55
我分别使用 vc6.0 和 gcc 10.2.0 编译了这个源程序,并使用 OllyDBG 仔细跟踪了两个程序的反汇编代 ...
感谢帮助
页:
[1]