【C】由printf("%d\t%d\t%d\n",a,a+=(a++),a);引起的思考

 1 #include<stdio.h>
 2 int main()
 3 {
 4     int a=1,a1=1;
 5     int b=1,b1=1;
 6     printf("(1)后自加:\n");
 7     printf("a+=(a++):\n");//
 8     printf("%d\t%d\t%d\n",a,a+=(a++),a);
 9     printf("%d\n",a);
10     printf("a1+(a1++):\n");//
11     printf("%d\t%d\t%d\n",a1,a1+(a1++),a1);
12     printf("%d\n",a1);
13 
14     printf("\n(2)前自加:\n");
15     printf("b+=(++b):\n");//
16     printf("%d\t%d\t%d\n",b,b+=(++b),b);
17     printf("%d\n",b);
18     printf("b1+(++b1):\n");//
19     printf("%d\t%d\t%d\n",b1,b1+(++b1),b1);
20     printf("%d\n",b1);
21     return 0;
22 }

总的来说挺纠结的,实际上面的结果计算涉及到如下几点:

(1) 当printf()参数表中有自加表达式时执行顺序:
后自加:8: printf("%d\t%d\t%d\n",a,a+=(a++),a);在VC6.0中的反汇编结果(见文末)为例:

1)倒数第一个参数入栈 这里值得注意的是入栈时数据占的字节数依据是参数表中该变量的数据类型,且float类型按照double类型的字节数)

2)倒数第二个参数入栈:取(a++)的值得① --> 计算①+a得② --> 把②赋值给a

3)倒数第三个参数入栈

4)控制字符串入栈

5)输出 这里值得注意的是输出时从栈中取数据时按照格式说明符对应的字节数,且%f对应double类型的字节数)

6)变量a自加1,并更新

自加:16: printf("%d\t%d\t%d\n",b,b+=(++b),b);在VC6.0中的反汇编结果(见文末)为例:

1)倒数第一个参数入栈

2)倒数第二个参数入栈:变量b自加1,并更新-->取b的值得① --> 计算b+①得② --> 把②赋值给b

3)倒数第三个参数入栈

4)控制字符串入栈

5)输出

(2)加法运算符'+'的计算顺序

这个也不用怀疑,计算顺序一定是先计算左操作数对应的表达式。

另外,要区分“计算”和“取值”的区别,如果左操作数只是一个变量,而右操作数是表达式。则先计算右操作数表达式的值,然后从左操作数的变量中取值再与该表达式相加。

因此: a+(++a)是 (变量a自加后数值+变量a自加后数值)而不是 (变量当前数值+变量a自加后数值)

 

以下是部分语句在VC6.0中反汇编结果:

  1 8:        printf("%d\t%d\t%d\n",a,a+=(a++),a);
  2 0040D75E   mov         eax,dword ptr [ebp-4]
  3 0040D761   push        eax
  4 0040D762   mov         ecx,dword ptr [ebp-4]
  5 0040D765   add         ecx,dword ptr [ebp-4]
  6 0040D768   mov         dword ptr [ebp-4],ecx
  7 0040D76B   mov         edx,dword ptr [ebp-4]
  8 0040D76E   mov         dword ptr [ebp-14h],edx
  9 0040D771   mov         eax,dword ptr [ebp-14h]
 10 0040D774   push        eax
 11 0040D775   mov         ecx,dword ptr [ebp-4]
 12 0040D778   push        ecx
 13 0040D779   push        offset string "%d\t%d\t%d\n" (00422fdc)
 14 0040D77E   mov         edx,dword ptr [ebp-4]
 15 0040D781   add         edx,1
 16 0040D784   mov         dword ptr [ebp-4],edx
 17 0040D787   call        printf (00401080)
 18 0040D78C   add         esp,10h
 19 9:        printf("%d\n",a);
 20 0040D78F   mov         eax,dword ptr [ebp-4]
 21 0040D792   push        eax
 22 0040D793   push        offset string "%c\n" (0042201c)
 23 0040D798   call        printf (00401080)
 24 0040D79D   add         esp,8
 25 10:       printf("a1+(a1++):\n");//
 26 0040D7A0   push        offset string "a1+(a1++):\n" (00422fd0)
 27 0040D7A5   call        printf (00401080)
 28 0040D7AA   add         esp,4
 29 11:       printf("%d\t%d\t%d\n",a1,a1+(a1++),a1);
 30 0040D7AD   mov         ecx,dword ptr [ebp-8]
 31 0040D7B0   push        ecx
 32 0040D7B1   mov         edx,dword ptr [ebp-8]
 33 0040D7B4   add         edx,dword ptr [ebp-8]
 34 0040D7B7   mov         dword ptr [ebp-18h],edx
 35 0040D7BA   mov         eax,dword ptr [ebp-18h]
 36 0040D7BD   push        eax
 37 0040D7BE   mov         ecx,dword ptr [ebp-8]
 38 0040D7C1   push        ecx
 39 0040D7C2   push        offset string "%d\t%d\t%d\n" (00422fdc)
 40 0040D7C7   mov         edx,dword ptr [ebp-8]
 41 0040D7CA   add         edx,1
 42 0040D7CD   mov         dword ptr [ebp-8],edx
 43 0040D7D0   call        printf (00401080)
 44 0040D7D5   add         esp,10h
 45 12:       printf("%d\n",a1);
 46 0040D7D8   mov         eax,dword ptr [ebp-8]
 47 0040D7DB   push        eax
 48 0040D7DC   push        offset string "%c\n" (0042201c)
 49 0040D7E1   call        printf (00401080)
 50 0040D7E6   add         esp,8
 51 13:
 52 14:       printf("\n(2)前自加:\n");
 53 0040D7E9   push        offset string "%d\t%d\n" (00422fc0)
 54 0040D7EE   call        printf (00401080)
 55 0040D7F3   add         esp,4
 56 15:       printf("b+=(++b):\n");//
 57 0040D7F6   push        offset string "b+=(++b):\n" (00422fa8)
 58 0040D7FB   call        printf (00401080)
 59 0040D800   add         esp,4
 60 16:       printf("%d\t%d\t%d\n",b,b+=(++b),b);
 61 0040D803   mov         ecx,dword ptr [ebp-0Ch]
 62 0040D806   push        ecx
 63 0040D807   mov         edx,dword ptr [ebp-0Ch]
 64 0040D80A   add         edx,1
 65 0040D80D   mov         dword ptr [ebp-0Ch],edx
 66 0040D810   mov         eax,dword ptr [ebp-0Ch]
 67 0040D813   add         eax,dword ptr [ebp-0Ch]
 68 0040D816   mov         dword ptr [ebp-0Ch],eax
 69 0040D819   mov         ecx,dword ptr [ebp-0Ch]
 70 0040D81C   push        ecx
 71 0040D81D   mov         edx,dword ptr [ebp-0Ch]
 72 0040D820   push        edx
 73 0040D821   push        offset string "%d\t%d\t%d\n" (00422fdc)
 74 0040D826   call        printf (00401080)
 75 0040D82B   add         esp,10h
 76 17:       printf("%d\n",b);
 77 0040D82E   mov         eax,dword ptr [ebp-0Ch]
 78 0040D831   push        eax
 79 0040D832   push        offset string "%c\n" (0042201c)
 80 0040D837   call        printf (00401080)
 81 0040D83C   add         esp,8
 82 18:       printf("b1+(++b1):\n");//
 83 0040D83F   push        offset string "b1+(++b1):\n" (00422fb4)
 84 0040D844   call        printf (00401080)
 85 0040D849   add         esp,4
 86 19:       printf("%d\t%d\t%d\n",b1,b1+(++b1),b1);
 87 0040D84C   mov         ecx,dword ptr [ebp-10h]
 88 0040D84F   push        ecx
 89 0040D850   mov         edx,dword ptr [ebp-10h]
 90 0040D853   add         edx,1
 91 0040D856   mov         dword ptr [ebp-10h],edx
 92 0040D859   mov         eax,dword ptr [ebp-10h]
 93 0040D85C   add         eax,dword ptr [ebp-10h]
 94 0040D85F   push        eax
 95 0040D860   mov         ecx,dword ptr [ebp-10h]
 96 0040D863   push        ecx
 97 0040D864   push        offset string "%d\t%d\t%d\n" (00422fdc)
 98 0040D869   call        printf (00401080)
 99 0040D86E   add         esp,10h
100 20:       printf("%d\n",b1);
101 0040D871   mov         edx,dword ptr [ebp-10h]
102 0040D874   push        edx
103 0040D875   push        offset string "%c\n" (0042201c)
104 0040D87A   call        printf (00401080)
105 0040D87F   add         esp,8
106 21:       return 0;
107 0040D882   xor         eax,eax
108 22:   }

 

posted @ 2016-03-16 23:54  wxiaoli  阅读(3174)  评论(0编辑  收藏  举报