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
- i++原理分析
- 文法G[E]分析表分析字符串(i+)-编译原理
- i=i++分析
- i++分析
- i++,++i,i=i+1 分析
- i++与i--的分析
- 再次分析i++与i--
- i++与++i经典分析
- Java I/O原理
- 计算机I/O原理
- java i/o原理
- 初始化列表-i++原理
- Linux I/O 原理
- 异步I/O原理
- 文件I/O原理
- java多线程原理-I
- Chromium Graphics: GPU客户端之间同步机制的原理和实现分析-Part I
- I()函数分析
- Myeclipse创建单元测试
- Effective Java读书笔记(二):方法、通用程序设计
- java-斐波那契数列
- Android Handler机制 (一个Thead中可以建立多个Hander,通过msg.target保证MessageQueue中的每个msg交由发送message的handler进行处理 ,但是
- DeepLearning学习笔记(一) 搭建环境
- i++原理分析
- npm 安装权限问题,在安装命令前加上,sudo即可
- 总结与备忘:nginx与php-fpm与php
- POJ 1979 && HDU 1312 Red and Black(DFS)
- kindeditor的使用方法简单介绍
- swift闭包--简明代码理解
- 修改oracle字符集将字符编码WE8MSWIN1252修改为AL32UTF8
- Android Listview 隐藏滚动条
- Android基础和运行机制