表达式如何工作c = ++ a + ++ a; [英] How the expression works c= ++a + ++a;

查看:70
本文介绍了表达式如何工作c = ++ a + ++ a;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

表达式如何在c c ++和java中工作

a = 10;

c = ++ a + ++ a;

输出:

在C:22

在Java中:23

在C ++中:24



为什么会发生这种情况任何人都能解释我这里++增量的实际工作是什么以及为什么答案不同。

解决方案

Hoo boy!

前后 - 理论上修复递增和递减操作非常简单,只有当人们发挥创意时才会在实践中遇到问题。基本上,前缀(++ i或--i​​)表示在使用变量之前增加或减少该值,因此变量立即具有新值:

 i =  10 ; 
x = ++ i + 5 ;



可以理解为:

 i =  10 ; 
i = i + 1 ;
x = i + 5 ;



和类似的 - 版本:

 i =  10 ; 
x = --i + 5 ;



可以理解为:

 i =  10 ; 
i = i - 1 ;
x = i + 5 ;



后缀版本(i ++或i--)执行同样的事情,但在使用变量之后:

 i =  10 ; 
x = i ++ + 5 ;



可以理解为:

 i =  10 ; 
x = i + 5 ;
i = i + 1 ;



类似

 i =  10 ; 
x = i-- + 5 ;



可以理解为:

 i =  10 ; 
x = i + 5 ;
i = i - 1 ;





是那呢?这有点......简单......



是的,确实如此。或者,也许不是。



这很简单,如果你以简单的方式使用它 - 作为数组索引器,例如:



 x = myArray [index ++]; 



或作为循环增量:



  for (i =  0 ;我<   10 ; i ++)
{
WriteLine(myArray [i] );
}



但在那之后,你进入一个充满困惑和痛苦的世界! 



例如,这会留下什么值 i



  int  i,j; 

i = 10 ;
for (j = 0 ; j < ; 5 ; j ++)
{
i = i ++;
}





答案是:不变。 仍为10.为什么?想象一下:如果我们扩展它会是什么样子?



  int  i =  10 ; 
i = i ++;





如果我们用C#写这个,那么IL看起来像这样:



。第14,14行:13,24''
IL_0001:ldc.i4.s 10将一个常数值1​​0推入堆栈,4字节整数,
IL_0003:stloc.0将堆栈顶部弹出到本地编号0
.line 15,15:13,21''
IL_0004:ldloc.0推送本地编号0到堆栈
IL_0005:dup复制堆栈顶部
IL_0006:ldc.i4.1推送一个常量值'1',4字节整数
IL_0007:添加Pop前两个堆栈项目,添加它们并推送结果
IL_0008:stloc.0将堆栈顶部存储在本地编号0
IL_0009:stloc.0将堆栈顶部存储在本地编号0





什么?在扩展的C#代码中,它返回:



  int  i =  10 ; 
int j = i;
int k = j;
k = k + 1 ;
i = k;
i = j;





这很奇怪......因为你可以扔掉中间的三条线而不影响结果。  



不应该那样做,应该吗?



是。是的,它应该:i ++是一个后缀操作:它说,记住i的值,然后将i递增1,然后返回你记住的值



所以你告诉编译器做的是通过用你开始时的值覆盖它来忽略增量的结果。



有趣的是,如果你在Visual Studio C ++编译器中尝试它...它不会...因为它以不同的方式处理它! 



所以,现在我们有了第一个原因,当你开始使用增量和减量运算符时,你必须要小心,实际上:它实际上是一个副作用,一行代码插入你的行,以及如果你不仔细思考,就不会按照你的想法行事。 



int i1 = i; i1 = i1 + 1; i = i



当您开始在同一行上混合操作时出现问题:

 i =  10 ; x = ++ i + i ++; 

问题在于语言规范没有准确定义何时应该进行预修复和后修复操作!这意味着它的具体实现与您得到的结果完全相同:i的值应始终相同:12但x的值可能因编译器而异(并且在目标处理器上的范围内 - 例如ARM已经内置了修复前后的增量并减少了它的机器代码LOAD操作,所以很有可能一个有效的编译器直接使用它们。它应该执行为:

 i =  10 ; 
i = i + 1 ;
x = i + i;
i = i + 1 ;

给出结果22或

 i =  10 ; 
i1 = i;
i = i + 1 ;
x = i1 + i;
i = i + 1 ;

其中21或

 i =  10 ; 
i1 = i;
i = i + 1 ;
x = i + i1;
i = i + 1 ;

这也是21不同的路线。

并且承受请注意,编译器不必按从左到右的顺序评估+的两个操作数,因此它甚至可以给出一些非常奇怪和意外的结果!像23 ...所以避免组合它们:将它们用于简单表达式,例如每次循环循环时递增数组索引,但不要花哨,否则你的代码可能会以有趣的方式失败......


how the expression works in c c++ and java
a=10;
c=++a + ++a;
output:
In C :22
In Java : 23
In C++ : 24

Why this happens can anyone explain me. what is the actual working of the ++ increment here and why the answers are different.

解决方案

Hoo boy!
Pre- and post- fix increment and decrement operations are pretty easy in theory, it's only when people get creative that you get problems in practice. Basically, a prefix (++i or --i) says to increase or decrease the value before you use the variable, so the variable has the new value immediately:

i = 10;
x = ++i + 5;


Can be read as:

i = 10;
i = i + 1;
x = i + 5;


and similarly for the -- version:

i = 10;
x = --i + 5;


Can be read as:

i = 10;
i = i - 1;
x = i + 5;


The postfix version (i++ or i--) does the same thing, but after the variable has been used:

i = 10;
x = i++ + 5;


Can be read as:

i = 10;
x = i + 5;
i = i + 1;


And similarly

i = 10;
x = i-- + 5;


Can be read as:

i = 10;
x = i + 5;
i = i - 1;



Is that it? It's a bit...simple...

Yes, it is. Or, perhaps not.

It is simple, if you use it in simple ways - as an array indexer for example:

x = myArray[index++];


Or as a loop increment:

for (i = 0; i < 10; i++)
   {
   WriteLine(myArray[i]);
   }


But after that, you are into a world of confusion and pain! 

For example, what does this leave as a value of i:

int i,j;

i = 10;
for (j = 0; j < 5; j++)
    {
    i = i++;
    }



The answer is: unchanged. i remains at 10. Why? Think of it like this: what does this look like if we expand it?

int i = 10;
i = i++;



If we write this in C#, then the IL looks like this:

.line 14,14 : 13,24 ''
IL_0001:  ldc.i4.s   10                    Push a constant value '10' to the stack, 4 byte integer, 
IL_0003:  stloc.0                          Pop the top of the stack into local number 0
.line 15,15 : 13,21 ''
IL_0004:  ldloc.0                          Push local number 0 to the stack 
IL_0005:  dup                              Duplicate the top of the stack
IL_0006:  ldc.i4.1                         Push a constant value '1', 4 byte integer
IL_0007:  add                              Pop the top two stack items, add them, and push the result
IL_0008:  stloc.0                          Store the top of the stack in local number 0
IL_0009:  stloc.0                          Store the top of the stack in local number 0



What? In expanded C# code, that comes back as:

int i = 10;
int j = i;
int k = j;
k = k + 1;
i = k;
i = j;



Which is rather strange...because you could throw away the three lines in the middle without affecting the results.  

It shouldn't do that, should it?

Yes. Yes, it should: i++ is a postfix operation: It says, "remember the value of i, then increment i by one, and then return the value you remembered".

So what you have told the compiler to do is ignore the result of the increment by overwriting it with the value you started off with.

Interestingly, if you try it in the Visual Studio C++ compiler...it doesn't... because it handles it differently! 

So, now we have the first reason why you have to be careful when you start using increment and decrement operators  for real: it's effectively a side effect, a whole line of code inserted into your line, and if you don't think very carefully, it won't do what you think. 

int i1 = i; i1 = i1 + 1; i = i

The trouble comes when you start mixing operations on the same line:

i = 10; x = ++i + i++;

The problem is that the language specification does not define exactly when pre- and post- fix operations should occur! Which means that it's implementation specific exactly what you get as a result: The value of i should always be the same: 12 but the value of x can be different depending on the compiler (and to an extent on the target processor - ARM for example has built in pre- and post- fix increment and decrement to it's "machine code" LOAD operations, so it would be quite likely that an efficient compiler would use them directly) Should it be executed as:

i = 10; 
i = i + 1; 
x = i + i; 
i = i + 1; 

Which gives the result 22 or as

i = 10; 
i1 = i; 
i = i + 1; 
x = i1 + i; 
i = i + 1;

Which gives 21 Or as

i = 10; 
i1 = i; 
i = i + 1; 
x = i + i1; 
i = i + 1;

which also gives 21 by a different route.
And bear in mind that the compiler does not have to evaluate the two operands of "+" in left to right order, so it could even give some very strange and unexpected results! Like 23... So avoid combining them: use them for "simple expressions" such as incrementing an array index each time round a loop, but don't get fancy, or your code may well fail in interesting ways...


这篇关于表达式如何工作c = ++ a + ++ a;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆