C语言,求大神解释一下最后结果是怎么算出来的~a1=18 a2=17 a3=16 a1=22,a

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.


下面的同理。纯手打。


温馨提示:答案为网友推荐,仅供参考
第1个回答  2014-12-31

这里有两个知识点:

    ++运算 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)]

第2个回答  2014-12-31

我实际用代码

  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

不过你思路是对的

本回答被提问者采纳
第3个回答  2014-12-31
你问的是printf的输出顺序还是什么?我就一块讲了吧。

首先a++那里,因为++在后,所以先比较后变化,因此经过3次+1,打印出来的结果会分别是
16,17,18,而这时的a=16+3=19,至于为什么顺序相反,则是printf的输出顺序问题,最后再讲。
然后++a那里,因为++在前,所以先变化,因此结果分别是19经过3次+1,依次是20,21,22。
最后,为什么是a1最大?也就是说为什么是a1处于变化的最后,最后才打印?
因为printf函数是从左往右读取,然后将先读取放到栈底,最后读取的放在栈顶,处理时候是从栈顶开始的,所有我们看见的结果是,从右边开始处理的。也就是你可以理解成是从右边开始变化,左边最后才变化,因此应得到上面所说的结果。
大致如此,不懂的可以再问我
第4个回答  2014-12-31
函数printf从左往右读取,然后将先读取放到栈底,最后读取的放在栈顶,处理时候是从栈顶开始的,所以我们看见的结果是,从右边开始处理的
a++和++a都是a=a+1的缩写,前者是先赋值后自加,后者是先自加后赋值
不管怎么样最终都是把整个表达式的值赋值给ai,所以就会出现那样的结果
同理对于x也一样
相似回答