C语言表达式/自增运算符:int a = 4;(++a) += (a++);中a值计算的思考!
摘自:http://hi.baidu.com/tomorrowguy/blog/item/cd83cdfbb2236e7e024f5611.html
其实说实话,这个表达式根本不具有实用性,而且其很有可能在不同的编译器下有着不同的解释,从而运行出不同的结果,极其不推荐使用这种写法,当然如果你想知道清楚,那希望你有耐心看我我的东西。。。
首先给出我的测试结果:
测试代码:
#include<stdio.h>
void main()
{
inta=4,b=4,c=4,d=4,e=4,f=4,g=4,h=4,j=4;
a+= (a++);
e=e+(e++);
b+= (++b);
d=d+(++d);
(++c)+=(c++);
(++f)=(++f)+(f++);
(++h)=(++h)+(++h);
(++j)=(j++)+(j++);
(++g)+=(++g);
printf("%d,%d,%d,%d,%d,%d,%d,%d,%d",a,e,b,d,c,f,h,j,g);
}
测试结果:
a=9;e=9
b=10;d=10
c=11;f=13
h=14;j=12
g=12
注:以上结果基于vc6.0编译器。
下面提下细节问题:
(++a) += (a++)不等价于 (++a)=(++a)+(a++) !!!
(注:基于vc6.0,其他编译器我不知道,待定。同时可以说明表达式中的此类括号的存在与否在vc6.0中是没有影响的,这个也因编译器而定。以后不再特别说明)
根据测试结果: (++c)+=(c++) 为11 ;(++f)=(++f)+(f++)为13 。可知两者其实并不等价,因为两者的算法不同,详见下面。
下面我提出我的基本观点: 前置自增运算符在一个表达式中其优先级是很高的,一般情形下,在一个算术运算表达式中其具有最高优先级。
若一个算术表达式f(++a1,++a2,++...,++an)中含有n个前置自增运算符,则此表达式的求解过程等价于:
++a1;
++a2;
++a3;
........
++an;
f(a1,a2,a3,...,an);//注意表达式的变化:f(++a1,++a2,++...,++an) 变为 f(a1,a2,a3,...,an)
下面讨论含有后置自增运算符时的情形,后置自增作用的变量是先用后增,从而若有一个算式表达式f(b1++,b2++,...++,bn++)中含有n个后置自增运算符,则此表达式的求解过程等价于:
f(b1,b2,b3,...,bn);
b1++;
b2++;
b3++;
........
bn++;
进一步拓展为: 若一个算式表达式f(++a1,++a2,++...,++an,b1++,b2++,...++,bn++)中含有n个前置自增运算符,和含有n个后置自增运算符,则此表达式的求解过程等价于:
++a1;
++a2;
++a3;
........
++an;
f(a1,a2,a3,...,an,b1,b2,b3,...bn);
b1++;
b2++;
b3++;
........
bn++;
下面举例证明:
1 :(++a) += (a++) 等价于:
++a;为5
a+=a;为a=10
a++;为11
2: (++f)=(++f)+(f++)等价于:
++f;为5
++f;为6
f=f+f;为12
f++;为13
其他各式都可如此证明,至此,证毕!
下面对此类表达式的语法进行初步讨论: 在表达式f(++a1,++a2,++...,++an,b1++,b2++,...++,bn++)中,并不是所有的情形都是能够通过编译的,那就是:在运算符=或+=等等,运算符的左边的单变量只能含有前置自增运算符,不能为带后置自增运算符的单变量,
即是说:
(++f)=(++f)+(f++);是合法的,
而
(f++)=(++f)+(f++);是非法的!!!
这个的具体机理我不知道,但是初步猜测为: 在左侧为前置自增运算符时,其自增计算在表达式的计算之前完成了,从而在计算表达式的值时此时左侧已经成为了单值变量,而不再是表达式,但是当左侧为后置自增运算符时,其在计算表达式的值时自增运算还没有进行,左侧为表达式,从而语法错误。 基于以上讨论,第三个表达式的使用是极力不推荐的!!!
下面给出能够通过编译的此类表达通式的计算等价形式:
表达式:++Value+=f(++a1,++a2,++...,++an,b1++,b2++,...++,bn++)的等价计算为:
++Value;
++a1;
++a2;
++a3;
........
++an;
Value=Value+f(a1,a2,a3,...,an,b1,b2,b3,...bn);
b1++;
b2++;
b3++;
........
bn++;
至此,完毕,谢谢阅读~~~
写在最后:此题目来源于一位百度知道的网友的提问,对在此引用其题目注以说明!
以下为本人补充的汇编代码:
1 1: #include <iostream> 2 2: 3 3: using namespace std; 4 4: 5 5: void addSelf() 6 6: { 7 00402AF0 push ebp 8 00402AF1 mov ebp,esp 9 00402AF3 sub esp,44h 10 00402AF6 push ebx 11 00402AF7 push esi 12 00402AF8 push edi 13 00402AF9 lea edi,[ebp-44h] 14 00402AFC mov ecx,11h 15 00402B01 mov eax,0CCCCCCCCh 16 00402B06 rep stos dword ptr [edi] 17 7: int a = 4; 18 00402B08 mov dword ptr [ebp-4],4 19 8: 20 9: (++a) += (a++); 21 00402B0F mov eax,dword ptr [ebp-4] 4+1 22 00402B12 add eax,1 23 00402B15 mov dword ptr [ebp-4],eax a=5 24 00402B18 mov ecx,dword ptr [ebp-4] 25 00402B1B add ecx,dword ptr [ebp-4] 5+5 26 00402B1E mov dword ptr [ebp-4],ecx a=10 27 00402B21 mov edx,dword ptr [ebp-4] 28 00402B24 add edx,1 a=a+1:a=10+1,即a=11 29 00402B27 mov dword ptr [ebp-4],edx