回 帖 发 新 帖 刷新版面

主题:让c语言和c++中的“a++,++a”永远不是问题

这里主要研究一下c语言和c++中的a++,++a
有分双操做数和多操做数之分
双操做数:(vc++,Turbo c)
在语言中定义a++是先用后加,++a是先加后用。
实际上对双操做数来说的是在一个语句中结束前加和后加的问题 。
即如k=(++a)+(a++);
a++是语句结束后在后加,
++a是先加后计算再语句结束。

我举几个例子(用vc反汇编说明)
1 int k=2;
int val=0;
val=(k++)+(k++);

反汇编
8:        int k=2;
00401028   mov         dword ptr [ebp-4],2//// k的地址是dword ptr [ebp-4]
9:        int val=0;    
0040102F   mov         dword ptr [ebp-8],0//val的地址是dword ptr [ebp-8]
10:       val=(k++)+(k++);
00401036   mov         eax,dword ptr [ebp-4]// 把2放入eax中
00401039   add         eax,dword ptr [ebp-4]// 把2+2=4放入eax中
0040103C   mov         dword ptr [ebp-8],eax//把eax中的4移回val中
0040103F   mov         ecx,dword ptr [ebp-4]
00401042   add         ecx,1//
00401045   mov         dword ptr [ebp-4],ecx//k地址中的值加1,k=3

00401048   mov         edx,dword ptr [ebp-4]
0040104B   add         edx,1// 寄存器中的值加1,k=4
0040104E   mov         dword ptr [ebp-4],edx//移回k地址

结论:val=*( dword ptr [ebp-8])=4;k=4

2. int k=2;
int val=0;
k=(k++)+(k++);

反汇编
:
8:        int k=2;
00401028   mov         dword ptr [ebp-4],2//同上
9:        int val=0;
0040102F   mov         dword ptr [ebp-8],0
10:       k=(k++)+(k++);
00401036   mov         eax,dword ptr [ebp-4]
00401039   add         eax,dword ptr [ebp-4] //同上
0040103C   mov         dword ptr [ebp-4],eax//同上,不同的是计算结果存入k地址k=4
0040103F   mov         ecx,dword ptr [ebp-4]
00401042   add         ecx,1//寄存器中的值加1,
00401045   mov         dword ptr [ebp-4],ecx//k=5
00401048   mov         edx,dword ptr [ebp-4]
0040104B   add         edx,1//寄存器中的值加1
0040104E   mov         dword ptr [ebp-4],edx//k=6

结论:k=*( dword ptr [ebp-4])=6;

3 int k=2;
int val=0;
val=(++k)+(++k);

反汇编:
8:        int k=2;
00401028   mov         dword ptr [ebp-4],2// k的地址是dword ptr [ebp-4]
9:        int val=0;
0040102F   mov         dword ptr [ebp-8],0//val的地址是dword ptr [ebp-8]
10:       val=(++k)+(++k);//k先加
00401036   mov         eax,dword ptr [ebp-4]
00401039   add         eax,1//寄存器中的值加1

0040103C   mov         dword ptr [ebp-4],eax//k=3
0040103F   mov         ecx,dword ptr [ebp-4]
00401042   add         ecx,1//对k地址中的值加1,k=4
00401045   mov         dword ptr [ebp-4],ecx
00401048   mov         edx,dword ptr [ebp-4]
0040104B   add         edx,dword ptr [ebp-4]//k+k=8
0040104E   mov         dword ptr [ebp-8],edx//值移入val地址中val=8

结论:val=*( dword ptr [ebp-8])=8;k=4
4. int k=2;
int val=0;
k=(++k)+(++k);
反汇编:
8:        int k=2;
00401028   mov         dword ptr [ebp-4],2
9:        int val=0;
0040102F   mov         dword ptr [ebp-8],0
10:       k=(++k)+(++k);
00401036   mov         eax,dword ptr [ebp-4]
00401039   add         eax,1
0040103C   mov         dword ptr [ebp-4],eax
0040103F   mov         ecx,dword ptr [ebp-4]
00401042   add         ecx,1
00401045   mov         dword ptr [ebp-4],ecx
00401048   mov         edx,dword ptr [ebp-4]
0040104B   add         edx,dword ptr [ebp-4]///以上同3例
0040104E   mov         dword ptr [ebp-4],edx// 值移入k地址k=8
结论:k=*( dword ptr [ebp-4])=8;

5. int k=2;
int val=0;
val=(++k)+(k++);

反汇编:


8:        int k=2;
00401028   mov         dword ptr [ebp-4],2
9:        int val=0;
0040102F   mov         dword ptr [ebp-8],0
10:       val=(++k)+(k++);
00401036   mov         eax,dword ptr [ebp-4]
00401039   add         eax,1
0040103C   mov         dword ptr [ebp-4],eax//k=k+1=3
0040103F   mov         ecx,dword ptr [ebp-4]
00401042   add         ecx,dword ptr [ebp-4]//k+k=6
00401045   mov         dword ptr [ebp-8],ecx//val=6
00401048   mov         edx,dword ptr [ebp-4]
0040104B   add         edx,1//k=k+1=4
0040104E   mov         dword ptr [ebp-4],edx

结论:val=*( dword ptr [ebp-8])=6;k=4

6. int k=2;
int val=0;
k=(++k)+(k++);

反汇编:

8:        int k=2;
00401028   mov         dword ptr [ebp-4],2
9:        int val=0;
0040102F   mov         dword ptr [ebp-8],0
10:       k=(++k)+(k++);
00401036   mov         eax,dword ptr [ebp-4]
00401039   add         eax,1//k+1
0040103C   mov         dword ptr [ebp-4],eax//k=3
0040103F   mov         ecx,dword ptr [ebp-4]
00401042   add         ecx,dword ptr [ebp-4]//k+k=6
00401045   mov         dword ptr [ebp-4],ecx//k=6
00401048   mov         edx,dword ptr [ebp-4]
0040104B   add         edx,1
0040104E   mov         dword ptr [ebp-4],edx//k=k+1=7

结论:k=*( dword ptr [ebp-4])=7;k=7

多操做数(vc++)
(Turbo c多操做数与两个操做数一样,由于编译器位数不同)


多操做数(>2)头两个操做数同以上(中间值)而后面的数如是(++i)加1
如是(i++)不加1。赋值给变量如果不是本身则结束
如果是本身则要数(i++)个数如是n加n
举几个例子(用vc反汇编说明)
1.
int k=2;
int val=0;
val=(k++)+(k++)+(++k);

反汇编:

331:  int k=2;
00407488   mov         dword ptr [ebp-14h],2
332:  int val=0;
0040748F   mov         dword ptr [ebp-18h],0
333:  val=(k++)+(k++)+(++k);
00407496   mov         eax,dword ptr [ebp-14h]
00407499   add         eax,dword ptr [ebp-14h]//以上同双操做数中间数存在eax中eax=4,k=2
0040749C   mov         ecx,dword ptr [ebp-14h]
0040749F   add         ecx,1
004074A2   mov         dword ptr [ebp-14h],ecx//k=3
004074A5   add         eax,dword ptr [ebp-14h]//eax+k=
004074A8   mov         dword ptr [ebp-18h],eax//赋值给val=eax+k=7
004074AB   mov         edx,dword ptr [ebp-14h]
004074AE   add         edx,1
004074B1   mov         dword ptr [ebp-14h],edx
004074B4   mov         eax,dword ptr [ebp-14h]
004074B7   add         eax,1
004074BA   mov         dword ptr [ebp-14h],eax

结论:val=*( dword ptr [ebp-18h])=6;k=5

2.
int k=2;
int val=0;
k=(k++)+(k++)+(++k);
反汇编:


331:  int k=2;
00407488   mov         dword ptr [ebp-14h],2
332:  int val=0;
0040748F   mov         dword ptr [ebp-18h],0
333:  k=(k++)+(k++)+(++k);
00407496   mov         eax,dword ptr [ebp-14h]
00407499   add         eax,dword ptr [ebp-14h]
0040749C   mov         ecx,dword ptr [ebp-14h]
0040749F   add         ecx,1
004074A2   mov         dword ptr [ebp-14h],ecx
004074A5   add         eax,dword ptr [ebp-14h]
004074A8   mov         dword ptr [ebp-14h],eax//赋值给k=eax+k=7
004074AB   mov         edx,dword ptr [ebp-14h]
004074AE   add         edx,1
004074B1   mov         dword ptr [ebp-14h],edx//k=k+1=8
004074B4   mov         eax,dword ptr [ebp-14h]
004074B7   add         eax,1
004074BA   mov         dword ptr [ebp-14h],eax//k=k+1=9

结论:val=*( dword ptr [ebp-14h])=9;

举个题(vc++下)
1.
int  k=2;
int  val =0;
val=(++k)+(++k)+(k++)+(++k) +(++k) +(++k) +(++k) +(k++)+(k++)+(k++);
val=4   +    4 +4    +5     +6     +7     +8     +8    +8     +8= 62

2.
int  k=2;
int  val =0;
k=(++k)+(++k)+(k++)+(++k) +(++k) +(++k) +(++k) +(k++)+(k++)+(k++);
4个k++
k=4   +    4+  4   +5     +6    + 7    +  8    +8    +8    +8  在加  4=66

在Turbo c 下

1.
int  k=2;
int  val =0;
val=(++k)+(++k)+(k++)+(++k) +(++k) +(++k) +(++k) +(k++)+(k++)+(k++);
6个++k,4个(k++)
6个++k运行后k=8,val=8*10=80;结束

2.
int  k=2;
int  val =0;
k=(++k)+(++k)+(k++)+(++k) +(++k) +(++k) +(++k) +(k++)+(k++)+(k++);
6个++k,k=80
4个(k++),k=80+4=84;

"a--,--a"与++a,a++相同

回复列表 (共14个回复)

沙发

不错吗
有能力
可以向你学习吗?
   你的QQ是多少?可以吗 ?

板凳

相互学习
我一般不上QQ

3 楼

有水平!

4 楼

如果用C语言解释,效果可能会更好。

5 楼

TO 楼主:
不好意思,我又有新问题啦,在我的贴子“(++i)+(++i)该怎么计算?”里,有位网友说在turrboc 2.0上,设x=3,则(x++)+(x++)+(++x)+(++x)=20。我试了一下,果然是这样啊。为什么visual c++和turrboc的运算结果不一样呢?

6 楼

这是由于编译器位数不同造成
在turbo c 下
双操作数是一样的
多操作数在turbo c 下与vc双操作数是不一样的


7 楼

a=0;
while(++a<10) a++;
b=0;
while(b++<10) ++b;


//结果会怎么样?晕了吧!

8 楼

谁都要谦虚,我别以为别人晕,其实是你晕
有问题就问,别用激将法没意意

基本语句结构执行过程都不清,还什么先加后加的

while(++a<10) a++;相当于

++a;
while( a<10 )
{
  a++;
  ++a;
}
while(b++<10) ++b;相当于
b++;
while( b<10 )
{
  b++;
  ++b;
}

当a=b=9;时进入循环时a,b都要加2 再执行判断,结果a=b=11

准确的过程
while(++a<10) a++;相当于
a+=1;
while(a<10)
{
   a+=1;
  a+=1;
}
if(a==10)
a+=1;

while(b++<10) ++b;相当于    
while(b<10)
{
  if(b==0)
     b+=1;
  else
    b+=1;

    b+=1;
}
if(b==10)
b+=1;



你晕再问,如何!别自命清高简单问题大家相互学习



9 楼

首先对楼主地钻研精神表示钦佩!

但是在实际使用中,绝对不要 在一个表达式中对同一个变量使用多次自加运算

如果这样的代码搬出去给老板看肯定要炒鱿鱼。另外,对于这种情况,C/C++的标准文档中没有任何说明,也就是说,只要可能,编译器想干什么就可以干什么,TC和MSC的运行结果就不一样,甚至你对同一个编译器选择不同的优化选项编译进行试验也可能会造成不同的结果。

反正有一点要注意:编程序绝对不要做出超出C/C++标准的事情,否则运行结果就是不可预测。

10 楼

这只是对语言的理解是原理性的当然编码要必勉二义性
编译原理必须要了解,哪能编译器想干什么就可以干什么
要对局面有预测性,才能控制你的程序

我来回复

您尚未登录,请登录后再回复。点此登录或注册