C语言,求大神解释一下最后结果是怎么算出来的~a1=18 a2=17 a3=16 a1=22,a2=21,a3=20
printf("a1 = %d, a2 = %d, a3 = %d\n",a++,a++, a++);
以上面这句为例,你要先明白两个知识点:
a++ 表示 把a先参加运算后加1。 ++a表示a在参加运算前先加1。
后面的3个a++运算顺序是从右到左,即是a3最先得到a的值,再到a2,再到a1,所以有a3 = 16,a2 = 17,a1 = 18;
printf("a1 = %d, a2 = %d, a3 = %d\n",++a,++a, ++a);
这时的a为19(因为刚a1 = 18的时候在运算完后加1),再从右到左,a3 = ++a = 20, a2 = 21,a1 = 22.
下面的同理。纯手打。
这里有两个知识点:
++运算 a++与++a的区别: a++返回a的值,再++,比如a=16,则a++表达式返回16,并且a的值变为17,而++a则现做++运算,最后使用a的值。
参数的压栈顺序,有些编译器左压,有些右压,也就是说,有些从左到右依次计算每一个参数,而另外一些编译器从右往左依次计算每一个参数
我们以VC编译器为例分析一下整数部分,浮点数类似(汇编面前,了无秘密)
37: printf("a1=%d,a2=%d,a3=%d\n",a++,a++,a++);
计算参数:最右边的a++,先将a值保留下来,此时a值为16,所以最右边的参数值是16
004138FE 8B 45 F8 mov eax,dword ptr [a]
00413901 89 85 20 FF FF FF mov dword ptr [ebp-0E0h],eax
00413907 8B 4D F8 mov ecx,dword ptr [a]
0041390A 83 C1 01 add ecx,1
0041390D 89 4D F8 mov dword ptr [a],ecx 然后将a增加1,此时a=17
计算参数:中间的a++,先将a值保留下来,此时a值为17,所以中间的值是17
00413910 8B 55 F8 mov edx,dword ptr [a]
00413913 89 95 1C FF FF FF mov dword ptr [ebp-0E4h],edx
00413919 8B 45 F8 mov eax,dword ptr [a]
0041391C 83 C0 01 add eax,1
0041391F 89 45 F8 mov dword ptr [a],eax 然后将a增加1,此时a=18
计算参数:最左边的a++,先将a值保留下来,此时a值为18,所以最左边的值是18
00413922 8B 4D F8 mov ecx,dword ptr [a]
00413925 89 8D 18 FF FF FF mov dword ptr [ebp-0E8h],ecx
0041392B 8B 55 F8 mov edx,dword ptr [a]
0041392E 83 C2 01 add edx,1
00413931 89 55 F8 mov dword ptr [a],edx
参数压栈:将前面保留的值通过寄存器压栈,打印显示,显示结果是a1=18,a2=17,a3=16
00413934 8B F4 mov esi,esp
00413936 8B 85 20 FF FF FF mov eax,dword ptr [ebp-0E0h]
0041393C 50 push eax
0041393D 8B 8D 1C FF FF FF mov ecx,dword ptr [ebp-0E4h]
00413943 51 push ecx
00413944 8B 95 18 FF FF FF mov edx,dword ptr [ebp-0E8h]
0041394A 52 push edx
0041394B 68 44 56 41 00 push offset string "a1=%d,a2=%d,a3=%d\n" (415644h)
00413950 FF 15 BC 82 41 00 call dword ptr [__imp__printf (4182BCh)]
00413956 83 C4 10 add esp,10h
00413959 3B F4 cmp esi,esp
0041395B E8 DB D7 FF FF call @ILT+310(__RTC_CheckEsp) (41113Bh)
38: printf("a1=%d,a2=%d,a3=%d\n",++a,++a,++a);
计算参数:右边的++a,因为++a表达式的返回值就是最新的a值,所以不需要保留
00413960 8B 45 F8 mov eax,dword ptr [a]
00413963 83 C0 01 add eax,1
00413966 89 45 F8 mov dword ptr [a],eax 此时a=20
计算参数:中间的++a,因为++a表达式的返回值就是最新的a值,所以不需要保留
00413969 8B 4D F8 mov ecx,dword ptr [a]
0041396C 83 C1 01 add ecx,1
0041396F 89 4D F8 mov dword ptr [a],ecx 此时a=21
计算参数:左边的++a,因为++a表达式的返回值就是最新的a值,所以不需要保留
00413972 8B 55 F8 mov edx,dword ptr [a]
00413975 83 C2 01 add edx,1
00413978 89 55 F8 mov dword ptr [a],edx 此时a=22
参数压栈:根据++a的函数,++a的返回值为当前a的值,所以每一个参数都取当前a的值,当前a=22
最后结果为:a1=22,a2=22,a3=22
0041397B 8B F4 mov esi,esp
0041397D 8B 45 F8 mov eax,dword ptr [a]
00413980 50 push eax
00413981 8B 4D F8 mov ecx,dword ptr [a]
00413984 51 push ecx
00413985 8B 55 F8 mov edx,dword ptr [a]
00413988 52 push edx
00413989 68 44 56 41 00 push offset string "a1=%d,a2=%d,a3=%d\n" (415644h)
0041398E FF 15 BC 82 41 00 call dword ptr [__imp__printf (4182BCh)]
我实际用代码
int a = 16;
printf("a1 = %d, a2 = %d, a3 = %d\n", a++, a++, a++);
printf("a1 = %d, a2 = %d, a3 = %d\n", ++a, ++a, ++a);
验证的结果为
a1 = 18, a2 = 17, a3 = 16
a1 = 22, a2 = 22, a3 = 22
-------------------------------------------------------------------------
至于你说的那个结果,可以这么解释:
printf 顺序打印,逆序计算。a++和++a,变量在前先用变量,符号在前先用符号,谁在前面先用谁。第一行的a1=18后,a自加1,变成19,第二行,先加1,变成20,所以从20开始。
第二个输出的结果为a1=22,a2=21,a3=20
不过你思路是对的
本回答被提问者采纳