Java-同样的语句,不同的结果

Java-同样的语句,不同的结果

甜柠檬 发布于 2017-10-27 字数 479 浏览 1340 回复 5

先看c++代码
#include <iostream>
using namespace std;
int main()
{
int a = 10;
a = a++;
cout << "The a is : " << a << endl;
return 0;
}
输出为11
java代码
public class Hello {
public static void main(String[] args) {
int a = 10;
a = a++;
System.out.println("a is : " + a);
}
}
输出为10,有人能解释一下吗?

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

归属感 2017-11-07 5 楼

你就假设java中a=a++;是先计算a++,此时,产生一个临时值是88, 然后a自增得89,接着a被赋值为临时值的88。

而C++中a=a++; 是运行完此句才自增所以是a被赋值一个a++的临时值88,然后a自增, a就是89。再者a=a++是未定义的.至少在c/c++里是这样.没有人这么a=a++用的

灵芸 2017-11-04 4 楼

我来说两句,这实际上就是常说的“副作用”与“序列点”,如果你学过C语言的话,会比较熟悉这个名词。根源就在于a++这种语法是没有定义的,不同的语言有不同的实现。
任何对这类问题的研究都是没有意义的。文档中明确地说明了。给你个参考地址
http://aiyooyoo.com/index.php/archives/449/
在高级语言如java,php中,是没有序列点这个概念的。它们的执行顺序总是固定的。所以这个,++的问题,并非优先级问题,而是序列点问题

瑾兮 2017-11-03 3 楼

这个应该与语言无关吧。这应该是编译器设计的问题,可能同样是c++语言,不同的编译器也可能得出a=10哦

晚风撩人 2017-11-01 2 楼

上面几位说的很全了,这种代码写了没用处,a=a++这种语义似乎就是没有严格定义的。

JAVA:
如果是a=a++,看一下字节码:

0 bipush 88 (int)
2 istore_1 //操作数栈顶的88到局部变量区[1]
3 iload_1 //局部变量区[1]到操作数栈顶
4 iinc LV-1 by 1 // 局部变量区[1]加1,局部变量区数值变为89
7 istore_1 //操作数栈顶的88到局部变量区[1],局部变量区数值变为88
8 getstatic java.lang.System.out
11 new java.lang.StringBuilder
14 dup
15 ldc "a is : " (java.lang.String)
17 invokespecial
20 iload_1 //局部变量区[1]到操作数栈顶为88
21 invokevirtual append
24 invokevirtual toString
27 invokevirtual println
30 return

如果是a++,字节码:

0 bipush 88 (int)
2 istore_1 //操作数栈顶的88到局部变量区[1]
3 iinc LV-1 by 1 // 局部变量区[1]加1,局部变量区数值变为89
6 getstatic java.lang.System.out
9 new java.lang.StringBuilder
12 dup
13 ldc "a is : " (java.lang.String)
15 invokespecial
18 iload_1 //局部变量区[1]到操作数栈顶为89
19 invokevirtual append
22 invokevirtual toString
25 invokevirtual println
28 return

从字节码上看,区别很明显,见注释。

C++:
VS
如果是a=a++,汇编码:

 0041170E mov dword ptr [a],58h
00411715 mov eax,dword ptr [a]
00411718 mov dword ptr [a],eax
0041171B mov ecx,dword ptr [a]
0041171E add ecx,1 //ecx 89
00411721 mov dword ptr [a],ecx

dword ptr [a]部分相当于白做功了。
如果是a++,汇编码:

 0041170E mov dword ptr [a],58h
00411715 mov eax,dword ptr [a]
00411718 add eax,1 //eax 89
0041171B mov dword ptr [a],eax

GCC,如果是a=a++:

 Dump of assembler code for function main:
0x00401318 <main+0>: push %ebp
0x00401319 <main+1>: mov %esp,%ebp
0x0040131b <main+3>: and $0xfffffff0,%esp
0x0040131e <main+6>: sub $0x10,%esp
0x00401321 <main+9>: call 0x401730 <__main>
0x00401326 <main+14>: movl $0x58,0xc(%esp)
0x0040132e <main+22>: incl 0xc(%esp)
0x00401332 <main+26>: mov $0x0,%eax // 89
0x00401337 <main+31>: leave
0x00401338 <main+32>: ret

这点汇编比较明显了。

晚风撩人 2017-10-30 1 楼

这个问题的原因是你理解错了 a++ 的意思,并不是a++有问题而是你赋值语句有问题
a++简单的理解就是 a = a + 1 所以你没必要再进行a=a++的赋值复杂的理解,a++本身是重载的运算符 而a++和++a的区别先引用a的值再+1,所以系统实现(抽象树)里应该有个临时变量 而a = a++
再者造成这种不同的根本原因恐怕是由于c++和java的设计思想不同造成的。c++里++运算符的意义是执行完当前语句之后,将目标值加1。而java是纯面向对象的。所有运算符都回被当作函数来对待。java中的++运算符和c++中重载++运算符很相似。