黑马程序员技术交流社区

标题: 关于自加运算的优先级问题 [打印本页]

作者: 郑雪    时间: 2013-4-28 17:17
标题: 关于自加运算的优先级问题
看这几个代码
int a = 2;
int b = a + 3 * a++;
System.out.println(b);
打印结果是8。

int a = 2;
int b = a++ + 3 * a;
System.out.println(b);
结果是11。

int a = 1;
int b = 2;
System.out.println(a+++b);
结果是3。

可不可以帮忙分析一下运算符的优先级啊,这几个结果究竟是怎么运算出来的啊?
作者: 吴波    时间: 2013-4-28 17:42
你这问题,最主要的没弄清楚a++的意思
你只要记:a++是先运算,再自增就好了
int a = 2;
int b = a + 3 * a++;//a是原值
System.out.println(a);//其实在这里可以打印下a的值,a=3
System.out.println(b);
打印结果是8。

int a = 2;
int b = a++ + 3 * a;//a先为原值2,由于a++运算完后等于3,所以后面3*a就为6
System.out.println(b);
结果是11。

int a = 1;
int b = 2;
System.out.println(a+++b);//同理a为原值1,再打印一次a就为2了
System.out.println(a);//2
结果是3。

作者: 绿树林    时间: 2013-4-28 17:52
三个算法的运算顺序如下
第一个:
a++
3 *(a++)
int b =a+(3 *(a++))

第二个:
a++
3 * a
int b = (a++) + (3 * a);

第三个:
a++
System.out.println((a++)+b);
作者: 付鑫鑫    时间: 2013-4-28 19:49
首先,a++与++a的区别是:
例如: int a =1;

作者: 付鑫鑫    时间: 2013-4-28 19:56
首先,a++与++a的区别是:
例如: int a =1;
         int b = a++;   此时的b的值为1;   先赋值运算,后自增
         int b =++a;     此时的b的值为2;  先自增,而赋值运算

接下就是按照我们小学的运算法则去算.
int a = 2;
int b = a + 3 * a++;
b = 2 + 3*2++;
b = 8;

接下来就按照这样的运算符的优先级

作者: cowthan    时间: 2013-4-28 20:05
关于++,我的个人理解:
1、不要依赖于类似于a + 3 * a++的表达式,结果可能是未定的,相信我,因为你不知道编译器是会先
给你处理第一个a,还是第二个a,如果是先处理第二个a,那结果就是9了,可能java编译器倾向于
按照从左到右处理,但是谁知道呢
2、表达式解析的原则是贪婪法则,类似于a+++b,看到第一个+,编译器不会停,会继续寻找是不是++,
所以这里是(a++)+b
3、对于a++,后缀++会产生两个结果,一个是用于表达式的结果,即a的本来的值,取出这个值之后,
会自增1,产生第二个结果,所以后缀++是一种副作用:
——首先返回原始值用于计算
——然后产生副作用,对a加1,影响下一次运算
4、对于++a,前缀++只能返回一个结果,即加1后的值,使用前缀你没法得到原始值

所以这样就可以理解C++为什么是C++,而不是++C,因为
C++的设计目的必须兼容C,但是又要有所改进,所以
C++应该产生两种结果,一种是C,一种是改进后的C,
所以命名为C++,如果当初C++之父那个谁谁谁不想兼容
C语言,那他就会取名为++C,不信你可以问他
作者: 邹晓慧    时间: 2013-4-28 20:11

复制代码
楼主其实你可以向上面那样输出一下



作者: 邹晓慧    时间: 2013-4-28 20:12
  1. class JiSuan{
  2.         public static void main(String[] args) {
  3.                 int a = 2;
  4.                 System.out.println("计算前a的值是:" + a);
  5.                 int b = a + (3 * (a++));
  6.                 System.out.println("计算后a的值是:" + a);
  7.                 System.out.println(b);
  8.                 //打印结果是8。

  9.                 int a1 = 2;
  10.                 System.out.println("计算前a1的值是:" + a);
  11.                 int b1 = a1++ + 3 * a1;
  12.                 System.out.println("计算后a1的值是:" + a);
  13.                 System.out.println(b1);
  14.                 //结果是11。

  15.                 int a2 = 1;
  16.                 int b2 = 2;
  17.                 System.out.println("计算前a2的值是:" + a);
  18.                 System.out.println(a2+++b2);
  19.                 System.out.println("计算后a2的值是:" + a);
  20.                 //结果是3。

  21.         }
  22. }
复制代码

作者: 董波    时间: 2013-4-28 20:43
首先,可以明确的是优先级从高到底肯定是++、*、+。那么为什么会出现这么奇怪的输出呢,要搞明白这个需要明确两点:1、a++是先取a的值供计算式使用,然后a自加;2、a++自加后的值虽然不影响此时自己在表达式中的值,但会使表达式中位于其后的a值加1。比如你的三个算式:
int b = a + 3 * a++;
第一个a取值为2;第二个a取值也为2,所以b=2+3*2=8;

int b = a++ + 3 * a;
第一个a取值为2;第二个a取值时,受前面a++的影响,取值为3,所以b=2+3*3=11;

int a = 1;
int b = 2;
System.out.println(a+++b);
a取值为1,b取值为2,结果是3。

其实只要记住a++只影响其后的a值就OK啦。比如,要是把你第一个算式"+"两边的部分交换一下:
int b = 3 * a++ +a;
它的输出结果就会变成9其实这就是因为后面的a受到了前面a++的影响加了1.(有点不符合加法交换律哈)

作者: 邵彩华    时间: 2013-4-28 21:16
本帖最后由 邵彩华 于 2013-4-28 21:32 编辑

看下面的|
作者: 邵彩华    时间: 2013-4-28 21:32
本帖最后由 邵彩华 于 2013-4-28 21:42 编辑

我来解答下楼主的疑问:
一、首先要弄明白楼主真正的迷惑,才能让楼主弄清问题。至于单纯的a++和++a的运算顺序,不用解释楼主肯定是明白的;我想楼主的迷惑应该是:在如上面的混合运算中,多处出现++a,a或a++楼主就不知道该怎么用a 的值了,对吧^^
二、其实很简单,就先拿第一个表达式来说吧!int b = a + 3 * a++; 这其实是个运算优先级的问题,我们在赋值运算时,先计算=号右边的表达式的值,也就是a+3*a++;这里很多人都容易犯一个错误,就是先计算了+号右边的乘除,再计算相加运算的值,如上面二楼和五楼的分析就是不正确的。真正的顺序是这样的: 对于+运算,应该从左至右运算,先算左边表达式的值,再算右边表达式的值,然后相加。此题左边表达式a的值是2, 右边表达式3*a++中因为++在变量a后面,所以先让a值参与运算后a自增,3*2=6,a再自增变成3,于是,b=2+6,a=3。
第二个表达式int b = a++ + 3 * a;赋值符号右边的表达式a++ + 3 * a,根据加法的从左至右的运算顺序,先算a++,由于++在变量后面,故先把a值用于运算再自增1,+号左边表达式参与加法运算的值为2,a自增1后变为3,变化后的a值继续参与+号右边的表达式运算3*a=9,最后b=2+9, a=3;
第三个表达式就不用我再分析了吧,楼主自会分析。
总结:
A: 对于++a和a++,前者a先自增1再用a的值参与下一个运算,后者是先把a的值用于下一个运算再让a自增1,但不论哪一种情况,只要出了(++a)或(a++)这个表达式,再去使用a,那就是在使用a变化后的值。
B:对于分析运算顺序时,符号的优先级我就不用说了自己去查,除此要注意一点:我们应该先分析优先级最低的运算符的运算顺序,找到其先运算的表达式后,再依次类推。  不要见到*或/,就不管在什么位置先去运算,这是一个误区。比如||,对于表达式1+2<4||3*2>6,肯定不会先去计算右边的乘法运算,不然||就不叫短路或了。
C、对于++a+++b---c之类的表达式,从左至右分析时,如果++或--左边的变量没有自加自减运算,则++或—应该先考虑给前面的变量。所以此表达式运算顺序为(++a)+(++b)-(--c); 表达式a+++b---c等同于(a++)+(b--)-c;表达式 ++a++是不存在的。

作者: 袁梦希    时间: 2013-4-28 22:05
郑雪   你一提出问题   老多人抢着答  哈哈哈
作者: 付鑫鑫    时间: 2013-4-29 08:12
int a = 2;
int b = a++ + 3 * a;
int b = 3 + 3*3;
int b = 11;
int a = 1;
int b = 2;
System.out.println(a+++b);
a++ + b ;
1 +2;
作者: cowthan    时间: 2013-4-29 14:49
邵彩华 发表于 2013-4-28 21:32
我来解答下楼主的疑问:
一、首先要弄明白楼主真正的迷惑,才能让楼主弄清问题。至于单纯的a++和++a的运算 ...

受教了哥们,还没见过这么全面的自增自减的分析
作者: 邵彩华    时间: 2013-4-29 15:02
cowthan 发表于 2013-4-29 14:49
受教了哥们,还没见过这么全面的自增自减的分析

呵呵 相互学习^^
作者: 花开花落总相似    时间: 2013-4-29 16:14
  这我也要学习一下  我去......
作者: 黄玉昆    时间: 2013-4-29 23:49
如果仍有问题,请继续追问,如果问题已解决,请将分类改为已解决,谢谢
作者: 七里香    时间: 2013-9-6 20:31
邵彩华 发表于 2013-4-28 21:32
我来解答下楼主的疑问:
一、首先要弄明白楼主真正的迷惑,才能让楼主弄清问题。至于单纯的a++和++a的运算 ...

谢谢了,你也解决了我的一个疑惑。不过教学时频里的优先级顺序那一段好像老师提供的资料不对貌似++ ——作为后缀的时候优先级没有二元运算符+ —高啊
作者: 七里香    时间: 2013-9-6 20:34
七里香 发表于 2013-9-6 20:31
谢谢了,你也解决了我的一个疑惑。不过教学时频里的优先级顺序那一段好像老师提供的资料不对貌似++ —— ...

而++ ——作为前缀的时候优先级比作为后缀要高。(补充上面的)




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2