i++原理分析

来源:互联网 发布:淘宝网首页包 编辑:程序博客网 时间:2024/04/19 16:32

今天遇到同学提出了一个题目,如下:
下列程序输出结果为:

#include<stdio.h>int main(){    char a[] = "123" ,*p;    p = a ;     printf("%c%c%c\n", *p++,*p++,*p++);     return 0 ; }

我觉得是111,但是实际上结果为123
这里写图片描述
我对C和C++了解并不是很深入,解释不了原因,然后我去用java试了试。
这道题我们主要的错误点在于对于++的理解,我就在java中只测试++,忽略题中对于指针的考察。
代码如下:

public class App {    public static void main( String[] args )    {        int i = 1;        System.out.println(i+++","+i+++","+i++);    }}

我认为会是1,1,1但还是1,2,3。其实之前只是知道i++是后加,但并不知道是在什么后加一。
于是去看一下字节码探个究竟:
上面程序的字节码如下:

Classfile /Users/zjchai/CodeSpace/Workspace/Maven/TestArchetype/target/classes/jack/test/App.class  Last modified 2016-3-23; size 768 bytes  MD5 checksum ea64c6e591bb2f46ea1f8ddc43509c91  Compiled from "App.java"public class jack.test.App  minor version: 3  major version: 45  flags: ACC_PUBLIC, ACC_SUPERConstant pool:   #1 = Methodref          #11.#27        // java/lang/Object."<init>":()V   #2 = Fieldref           #28.#29        // java/lang/System.out:Ljava/io/PrintStream;   #3 = Class              #30            // java/lang/StringBuffer   #4 = Methodref          #3.#27         // java/lang/StringBuffer."<init>":()V   #5 = Methodref          #3.#31         // java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;   #6 = String             #32            // ,   #7 = Methodref          #3.#33         // java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;   #8 = Methodref          #3.#34         // java/lang/StringBuffer.toString:()Ljava/lang/String;   #9 = Methodref          #35.#36        // java/io/PrintStream.println:(Ljava/lang/String;)V  #10 = Class              #37            // jack/test/App  #11 = Class              #38            // java/lang/Object  #12 = Utf8               <init>  #13 = Utf8               ()V  #14 = Utf8               Code  #15 = Utf8               LineNumberTable  #16 = Utf8               LocalVariableTable  #17 = Utf8               this  #18 = Utf8               Ljack/test/App;  #19 = Utf8               main  #20 = Utf8               ([Ljava/lang/String;)V  #21 = Utf8               args  #22 = Utf8               [Ljava/lang/String;  #23 = Utf8               i  #24 = Utf8               I  #25 = Utf8               SourceFile  #26 = Utf8               App.java  #27 = NameAndType        #12:#13        // "<init>":()V  #28 = Class              #39            // java/lang/System  #29 = NameAndType        #40:#41        // out:Ljava/io/PrintStream;  #30 = Utf8               java/lang/StringBuffer  #31 = NameAndType        #42:#43        // append:(I)Ljava/lang/StringBuffer;  #32 = Utf8               ,  #33 = NameAndType        #42:#44        // append:(Ljava/lang/String;)Ljava/lang/StringBuffer;  #34 = NameAndType        #45:#46        // toString:()Ljava/lang/String;  #35 = Class              #47            // java/io/PrintStream  #36 = NameAndType        #48:#49        // println:(Ljava/lang/String;)V  #37 = Utf8               jack/test/App  #38 = Utf8               java/lang/Object  #39 = Utf8               java/lang/System  #40 = Utf8               out  #41 = Utf8               Ljava/io/PrintStream;  #42 = Utf8               append  #43 = Utf8               (I)Ljava/lang/StringBuffer;  #44 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuffer;  #45 = Utf8               toString  #46 = Utf8               ()Ljava/lang/String;  #47 = Utf8               java/io/PrintStream  #48 = Utf8               println  #49 = Utf8               (Ljava/lang/String;)V{  public jack.test.App();    descriptor: ()V    flags: ACC_PUBLIC    Code:      stack=1, locals=1, args_size=1         0: aload_0         1: invokespecial #1                  // Method java/lang/Object."<init>":()V         4: return      LineNumberTable:        line 3: 0      LocalVariableTable:        Start  Length  Slot  Name   Signature            0       5     0  this   Ljack/test/App;  public static void main(java.lang.String[]);    descriptor: ([Ljava/lang/String;)V    flags: ACC_PUBLIC, ACC_STATIC    Code:      stack=3, locals=2, args_size=1         0: iconst_1         1: istore_1         2: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;         5: new           #3                  // class java/lang/StringBuffer         8: dup         9: invokespecial #4                  // Method java/lang/StringBuffer."<init>":()V        12: iload_1        13: iinc          1, 1        16: invokevirtual #5                  // Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;        19: ldc           #6                  // String ,        21: invokevirtual #7                  // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;        24: iload_1        25: iinc          1, 1        28: invokevirtual #5                  // Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;        31: ldc           #6                  // String ,        33: invokevirtual #7                  // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;        36: iload_1        37: iinc          1, 1        40: invokevirtual #5                  // Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;        43: invokevirtual #8                  // Method java/lang/StringBuffer.toString:()Ljava/lang/String;        46: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V        49: return      LineNumberTable:        line 7: 0        line 8: 2        line 9: 49      LocalVariableTable:        Start  Length  Slot  Name   Signature            0      50     0  args   [Ljava/lang/String;            2      48     1     i   I}SourceFile: "App.java"

这个挺烦的,我们只看public static void main(java.lang.String[]);之后的code结合上面的Constant pool。
按照代码序号依次解释什么意思:
0:将1入操作数据栈;
1:将栈顶元素保存到第一个临时变量(i);
2,5不解释
8:是为9的构造函数准备的;
12:将第一个临时变量(i)的值入栈;
13:将第一个临时变量加1,不影响栈,即在临时变量区自加;
16,19,21:不解释了,就是执行append方法把栈顶数据加进去此时这个数值为1,局部变量区的数值是2了已经;
24:即又是把第一个临时变量(i)的值(2)入栈;
25:又是局部变量的第一个元素(i)自己加一变成3了,且不影响栈;
。。。
我相信下面就都会了。
因此我们可以看到,++为后缀的话,从字节码的角度上看是执行完load之后加一。如果为前缀我试了,就是在load之前,有兴趣可以自己试一下。

0 0
原创粉丝点击