你确定这还是你认识的 j++ 吗?

最近偶然看到一个有意思的东西,不是很高端,但很有意思。

先看下面这段Java代码:

public class Test {
    public static void main(String args[]){
        int j = 0;
        for(int i = 0; i < 10; i++){
            j = j++;
        }
        System.out.println("j = " + j);
    }
}

       问题来了,运行上述代码输出的值是多少?在没有自己尝试之前,相信不少人心里也犯嘀咕。很多人都会想,这么简单的问题,肯定是10呀。然而一运行发现 结果为0,什么情况,为什么是0而不是10呢?让我们来简单分析一下。

       首先可以明确的一点是赋值运算的运算方向是从右到左。那么其他呢?只能借助于查看编译后的字节码。于是用以下命令查看(为了剔除冗余信息,此处只在main方法里面写上 j=j++ ):

Javap -c Test

Test是编译后的class文件,之后你会看到下面的一些东西:

Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1        // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0                //将常量0压入操作数堆栈
       1: istore_1                //从操作数栈中取出值到本地变量
       2: iload_1                 //将本地位置1的值压入操作数堆栈
       3: iinc          1, 1      //本地位置1的值加1,不改变操作数堆栈
       6: istore_1                //从操作数栈中取出值到本地位置1(上一步自加的值被覆盖)
       7: return
}
这里附上一些比较常见指令的博文讲解及官方文档:

到这里,你应该知道为啥结果为0了吧。j++ 的值压根没用到就被覆盖了,也可以说执行 j++ 之后j的值的确为1了,但是 j++ 并未改变堆栈的值,执行赋值语句的时候就又把j的值置零了。

local variable operand stack
—————— 0
0 0
1 0
0 0

即堆栈里面的值自始至终都是0。

  • 看完了Java,再看看PHP中的情况,运行如下代码:
< php
$j = 0;
for($i = 0; $i < 10; $i++){
    $j = $j++;
}
echo "j = $j";

结果如同Java一样,输出为j=0,可见PHP采用和Java类似的方式处理j=j++这条语句。

  • 然后再看看C++
#include <iostream>
using namespace std;

int main(){
    int j = 0;
    for(int i = 0; i < 10; i++){
        j = j++;
    }
    cout << "j=" << j << endl;
    return 0;
}

此处用GCC编译,之后点击运行,没问题,结果为0,和Java中一样。现在三中语言得到同样的结果,那是不是可以肯定结果必定为0呢,我们接着尝试。

  • 看看C语言中如何处理
#include <stdio.h>

int main(){
    int i = 0, j = 0;
    for(i = 0; i < 10; i++){
        j = j++;
    }
    printf("j=%d", j);
    return 0;
}

同样用gcc编译运行,和前面一样,结果也为0。现在再次问自己结果定了吗?其实不然。接下来我们换个编译器看看。用微软VS编译试试,结果一运行,结果输出 j=10。C/C++ 都这样,输出10。可见,对于C/C++来说编译器也有讲究。

总结

虽然代码存在上述情况,但是好在一般程序员都不太会写出 类似 'j=j++' 这样的代码,而且目前一些IDE已经能够给出警告:比如对于JAVA来说 intellij idea 会有以下提示:
文章正文图片

所以这种差异性也不会造成大的危害。但是对于新手情况就不一样了,遇到这样的问题,足以让其困惑良久。

以上所有内容只是我自己的理解,如若有误,欢迎留言或者Email指出。

It's
欢迎访问本站,欢迎留言、分享、点赞。愿您阅读愉快!
*转载请注明出处,严禁非法转载。
https://www.devsong.org
QQ留言 邮箱留言
头像
引用:
取消回复
提交
涂鸦
涂鸦
热门