2 u010712045 u010712045 于 2015.06.13 17:33 提问

同样是a++同样是*3结果为什么不一样呢

int a=2 ;int b=a+3*a++
int a=2 ;int b=(a++)+3*a
第一个b=8第二个b=11
结果为什么不一样啊

9个回答

danielinbiti
danielinbiti   Ds   Rxr 2015.06.13 22:05
已采纳
 哎,怎么还这帖子呀,这实际单纯是编译器谁写的就是什么规则。
从java来说,一个表达式来了,边扫描边取数,符合规则就计算,不是说一看到表达式就去计算运算符的优先级高的部分,它也得从左往后解析过去。
int b=a+3*a++
就比如上面这句话,表达式是a+3*a++,从左往后扫描,扫描到a,取a的值2,后面是+号,+号运算需要2个数,还需要往下扫描一个数,扫描到是3,但发现3后面是*,优先级高于+号,乘号也是需要2个数,接着取下一个数a(值是2),再往下扫描是++,优先级高于*号。
根据扫描顺序,你可以得到一个独立的指令列表(栈)2,3,2,++,*,+这么一组指令。执行++后,原来的a的值是3(这改的不是栈中的,是a变量的值),所以表达式计算中还是2*3+2

如果上面表达式改成
int b=3*a++ + a的话,那结果就不一样了
从左往右扫描,取常数3,往下扫描是乘号,需要再取一个数,是a,取a的值2,接着扫描下一个,发现是++,优先级高于乘号。接着往下扫描,发现是+号,优先级低于前面。则前面可以先运算了。
前面的指令列表是 3,2,++,*。执行++,原来的a的值是3(这改的不是栈中的,是a变量的值),执行乘,3*2=6,这是后再看是+号,取下一个数,是a,取值,这时候值是3了,已经改变了。所以变成6+3=9.


大概过程是这么一个过程。
各种语言同一行的编译和执行方式都有些差异的,这得看具体的语言,比如C语言就不会出现9。
如果自己还不清楚,建议去看看JVM相关的指令编译和执行过程相关的内容。

另外,把前面的帖子结了吧。

danielinbiti
danielinbiti 回复u010712045: 因为+号的优先级低。
2 年多之前 回复
u010712045
u010712045 后面的a怎么不接着扫描啦
2 年多之前 回复
u010712045
u010712045 int b=3*a++ +a为什么扫描到+后前面的就开始计算啦
2 年多之前 回复
caozhy
caozhy   Ds   Rxr 2015.06.13 18:27

再和你说一次,这是未定义行为。未定义行为的结果取决于编译器的实现,没有任何为什么可以问。
除非你拿编译器的实现,以及编译器产生的目标代码去分析,但是这是本末倒置的。
另外,a++表达式求值和a++表达式是两个不同的概念。

gamefinity
gamefinity   Rxr 2015.06.13 17:41

还在纠缠这个问题啊。
这个问题解释了比不解释还不好。因为每个C/C++的实现可能是不一样的,不能保证在这个编译环境下的结果是11,就是所有的编译环境下都是11
简单来说就是.a++是先用后加.在这里我们看到的是按表达式的顺序来计算的.每个子表达式完成后,马上计算++;但是也有的编译器是把表达式全部计算完之后再统一计算++的.
所以最好的办法就是别用这样的方法

u010712045
u010712045 这两个概念不同在哪里
2 年多之前 回复
ycg514230
ycg514230 回复u010712045: 你去看看,运算的时候优先级高的先计算。http://www.cnblogs.com/gw811/archive/2012/10/13/2722752.html
2 年多之前 回复
gamefinity
gamefinity 回复u010712045: 没试过。总之这种方式不好,建议别用
2 年多之前 回复
u010712045
u010712045 在java环境下呢
2 年多之前 回复
u010712045
u010712045   2015.06.13 20:20

就一点想不明白b=a+3*a++不应该是b=3+3*2呢

gamefinity
gamefinity 这样说吧。你说的b=a+3*a++不管在哪种编译器,都不会是b=3+3*2。我告诉你为什么。你学过表达式求值的吧,这个是栈的典型应用案例。好了,我们现在分析这个表达式。当它读到a+的时候,它先把a(2)push进栈了,因此后面不管a怎么变化,栈里面的值是不会再变化了。这样解释你清楚一点了么?再次说明,这个事情没有讨论的必要,不要这样写就好了
2 年多之前 回复
u010712045
u010712045   2015.06.14 01:14

非常感谢各位大神的解答 使我明白了 特别是caozhy和danielinbiti这两位大神对于我多次提同一个问题非但没有感到厌烦而且还多次悉心的回答 使我非常感动 我是新手菜鸟 未来学习编程的路还很长 希望得到各位大神的教导 希望各位大神能多传授我点经验和知识
谢谢

zhi_ai_yaya
zhi_ai_yaya   Rxr 2015.06.15 09:55

蛋疼的想法。
为啥要搞出这些带有二义性的代码了,让后面维护的娃情可以堪。出于业界良心,还是加圆括号指明优先级吧。

int a=2 ;int b=(a++)+3*a
像这个,蛋碎一地呀,不要想当然a++会先被执行呀,加法是有交换律的,但是编译器并没有交换律!!!

ycg514230
ycg514230   Rxr 2015.06.13 17:39

第一个是先*3再加,加的没有意义,等价于
int a=2 ;int b=a+3*a;;a=a+1;
第二个是先加,然后再乘,等价于
int a=2 ;a=a+1;int b=a+3*a;

u010712045
u010712045 不是a++自加后a不是不是变成3啦吗 不是b=3+3*2吗
2 年多之前 回复
caozhy
caozhy 回复帘卷西风: 昨天说了半天都白说了。
2 年多之前 回复
ycg514230
ycg514230 回复caozhy: 你这扯淡吧,编译器如果连这个都不能区分,还设计这个操作干嘛
2 年多之前 回复
caozhy
caozhy 和优先级没有任何关系,优先级是语法规范。这里之所以是未定义行为,是因为a++是一个副作用表达式,副作用表达式是否影响表达式求值是不能保证的。
2 年多之前 回复
ycg514230
ycg514230 回复u010712045: java的自增运算的优先级比括号低,但是比+-/*都要高啊,你可以上网查一下
2 年多之前 回复
u010712045
u010712045 但是不符合java的优先级啊
2 年多之前 回复
u012216727
u012216727   Ds   Rxr 2015.06.13 18:10

int a=2 ;int b=a+3*a++
int a=2 ;int b=(a++)+3*a

第一行b=2+3*2=8,然后a++,a=3;
第二行,先是括号中(a++);这个结果是(a++)=2,然后a++,a=3;
最后b=2+3*3=11
你可以对照着看看

EnderSnow
EnderSnow   2015.06.13 18:38

从左到右计算,注意a++是在a运算后再自己+1,就像a++和++a的区别一样

u010712045
u010712045 不是按优先级吗
2 年多之前 回复
u010712045
u010712045 为什么是从左到右计算呢
2 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片