关于前置++和后置++

一般认为前置++是先将变量的值加1,然后使用加1后的值参与运算;而后置++是先使用该值参与运算,然后再将该值加1。

先看第一个例子:

package test;
public class Plus_Test01 {
    public static void main(String[] args) {
        int i = 100;
        i = i++;
        System.out.println(i);
    }
}

猜猜结果是什么?

接着看第二个:

package test;
public class Plus_Test02 {
    public static void main(String[] args) {
        int k = 100;
        while (true) {
            if (k++ > 100) {
                // System.out.println(k);
                break;
            }
            System.out.println(k);
        }
    }
}

猜猜结果是什么?

实际上,不管是前置++,还是后置++,都是先将变量的值加1,然后才继续计算的。二者之间真正的区别是:前置++是将变量的值加1后,使用增值后的变量进行运算的,而后置++是首先将变量赋值给一个临时变量,接下来对变量的值加1,然后使用那个临时变量进行运算。

对于如下代码片段(前置++):

int i=1;
int j=++i*5;

实际第二句上相当于:

i+=1; //将i加1
j=i*5; //将加1后的值与之进行计算, 此结果为:10

而对于如下代码片段(后置++):

int i=1;
int j=i++*5;

第二句上相当于:

int temp=i;  // 将i赋值给一个临时变量
i+=1;        //将i加1
j=temp*5;   //将临时变量与之计算, 此结果为:5

对于第一个例子,相当于:

int temp=i;
i+=1;
i=temp; //

所以结果应该为不变的,即100。

第一个例子的汇编代码为:

 1 public static void main(java.lang.String[]);
 2     descriptor: ([Ljava/lang/String;)V
 3     flags: ACC_PUBLIC, ACC_STATIC
 4     Code:
 5       stack=2, locals=2, args_size=1
 6          0: bipush        100
 7          2: istore_1
 8          3: iload_1
 9          4: iinc          1, 1  //local var中第二个 加1
10          7: istore_1             //保存至local var
11          8: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
12         11: iload_1   //加载的参数为栈中的第二个,即仍然为100
13         12: invokevirtual #22                 // Method java/io/PrintStream.println:(I)V
14         15: return

对于第二个例子,其实不难,结果是101,注意看一下流程,以后不能在犯这样的错误了。(流程为:首先比较temp=i,temp>100,,显然不成立,将i+=1,跳到syso那一句,打印的当然是101,再次循环同样有temp=i,temp>100,这次是成立的,然后i+=1,直接跳出循环,不会执行while里面的语句)。

第二个例子的汇编(只选取了main方法):

 1 public static void main(java.lang.String[]);
 2     descriptor: ([Ljava/lang/String;)V
 3     flags: ACC_PUBLIC, ACC_STATIC
 4     Code:
 5       stack=2, locals=2, args_size=1
 6          0: bipush        100       //100压栈
 7          2: istore_1                  //保存至第二个local var(第一个local var 是方法参数)
 8          3: iload_1                  //从第二个local var加载
 9          4: iinc          1, 1       //给local var的2号位置的int值增加1(局部变量自增,结果仍然在local var中,操作数栈顶1不会变)
10          7: bipush        100    //100压栈
11          9: if_icmple     15  //比较操作数栈顶的两个int整型值,如果第一个小于或者等于第二个的话,然后跳转到15行
12         12: goto          25   //否则跳转到25行(即操作数栈顶1>操作数栈顶2)
13         15: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
14         18: iload_1   //  //从第一个个local var加载
15         19: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V  //调用该方法
16         22: goto          3  //再次回跳至3,再次循环
17         25: return  //退出

第三个例子:

 1 package test;
 2
 3 public class Plus_Test03 {
 4
 5     static int proPlus() {
 6         int i = 55;
 7         int j = ++i;
 8         return j; //56
 9     }
10
11     static int postPlus() {
12         int i = 55;
13         int j = i++;
14         return j; //55
15     }
16
17     public static void main(String[] args) {
18         System.out.println(proPlus());//56
19         System.out.println(postPlus());//55
20
21     }
22 }

第三个例子的汇编:

static int proPlus();
    descriptor: ()I
    flags: ACC_STATIC
    Code:
      stack=1, locals=2, args_size=0
         0: bipush        55   //55压栈
         2: istore_0         //将int型栈顶的存储至第一个local var
         3: iinc          0, 1  //第一个local var加1
         6: iload_0         //从local var加载
         7: istore_1       //保存至第二个local var
         8: iload_1         //栈顶为第二个local var
         9: ireturnstatic int postPlus();
    descriptor: ()I
    flags: ACC_STATIC
    Code:
      stack=1, locals=2, args_size=0
         0: bipush        55
         2: istore_0
         3: iload_0             //加载至栈
         4: iinc          0, 1   //第一个local var加1
         7: istore_1
         8: iload_1
         9: ireturn

可见,前置++ 和后置++的不同点在于上面蓝色的部分,这两部分是反过来的。对于前置来说,会将local var中的数加1然后加载至栈中,而后置则是先从栈local var中加载至栈,然后将local var的加1,相当于留了一个备份。

结论:

一。前置、与后置++都是先将变量的值加1,而不是前置++先加1然后运算,而后置++先运算后加1。
二。从程序上说,后置++先将变量赋值给一个临时变量,然后将变量的值加1,接下来使用那个临时变量参与运算。
三。从指令上说,后置++在执行增值指令(iinc)前,先将变量的值压入栈,执行增值指令后,使用的是之前压入栈的值。

时间: 2024-10-09 02:55:51

关于前置++和后置++的相关文章

ThinkPHP - 前置操作+后置操作

前置操作和后置操作 系统会检测当前操作(不仅仅是index操作,其他操作一样可以使用)是否具有前置和后置操作,如果存在就会按照顺序执行,前置和后置操作的方法名是在要执行的方法前面加 _before_和_after_,例如: class CityAction extends Action{ //前置操作方法 public function _before_index(){ echo 'before<br/>'; } public function index(){ echo 'index<

android Camera 如何判断当前使用的摄像头是前置还是后置

现在 android 平台的智能手机一般都标配有两颗摄像头.在 Camera 中都存在摄像头切换的功能. 并且有一些功能前后置摄像头上会有所不同.譬如人脸检测,人脸识别,自动对焦,闪光灯等功能, 如果前置摄像头的像素太低,不支持该功能的话,就需要在前置摄像头上关掉该 feature. 那么是如何判断并切换前后置摄像头的呢? 我们先来看下 CameraInfo 这个类, 1 /** 2 * Information about a camera 3 */ 4 public static class

前置及后置++,--

关于前置及后置++,-- a++ (temp=a,a+=1,temp) //由此看出后置++产生临时变量 ++a (a+=1,a) 所以在程序中出现a++=10,(a++)++,++(a++)等试图改变后置++的值,是错误(编译错误)的 前置及后置++的用法 1.遇到逗号结束: 如:int a=10; int c=(a++,++a,a++); printf("%d\n",c); 在VC6中打印c的值为12,这里的(a++,++a,a++);为逗号表达式,从左向右运算,遇逗号后置++进行

ThinkPHP3.2基础教程(36)--控制器-前置和后置操作

前置和后置操作指的是在执行某个操作方法之前和之后会自动调用的方法,不过仅对访问控制器有效. 其他的分层控制器层和内部调用控制器的情况下前置和后置操作是无效的. 系统会检测当前操作是否具有前置和后置操作,如果存在就会按照顺序执行,前置和后置操作的定义方式如下: <?php namespace Home\Controller; use Think\Controller; class IndexController extends Controller{ //前置操作方法 public functio

前置和后置自增以及解引用重载函数(++、--、*)

#include<iostream> using namespace std; class INT { private: int m_i; public: INT(int i):m_i(i){} // 区分前置和后置自增重载函数的区别是是否有参数,以及参数的个数 // 如果是前置自增,比如++a,因为++符号前面没有变量,于是重载函数也就没有参数 INT& operator++() { ++(this->m_i); return *this; } const INT operat

(转)前置++和后置++的区别

今天在阅读<google c++ 编程风格>的文档的时候,5.10. 前置自增和自减:有一句话引起了我的注意: 对于迭代器和其他模板对象使用前缀形式 (++i) 的自增, 自减运算符.,理由是 前置自增 (++i) 通常要比后置自增 (i++) 效率更高.于是我查了查前置++和后置++的区别. 注意:<more effective c++>条款8也专门叙述了问题.后来我发现,下面的文章基本就是它的翻版,哈哈 前置++和后置++的区别 <C专家编程>中有如下描述(P276

深入理解递增,前置与后置

当x++与++x独占一行是,它们的功能是相似的,都可以看做x=x+1; 当x++与++x嵌入在表达式里面的时候,x++是先x+1,在执行表达式:而++x是先执行表达式,再x+1. 例子 x=10; y=10; if(++x==11){}   True; if(y++==11){}   False; 深入理解递增,前置与后置

spring的几个通知(前置、后置、环绕、异常、最终)

1.没有异常的 2.有异常的 1.被代理类接口Person.java 1 package com.xiaostudy; 2 3 /** 4 * @desc 被代理类接口 5 * 6 * @author xiaostudy 7 * 8 */ 9 public interface Person { 10 11 public void add(); 12 public void update(); 13 public void delete(); 14 } 2.被代理类PersonImple.java

JavaScript运算符:递增递减运算符前置和后置的区别

从两段代码说起 var num1 = 2; var num2 = 20; var num3 = --num1 + num2; var num4 = num1 + num2; console.log(num1 +'-' + num2 +'-'+ num3 +'-' + num4) 将四个数分别打印是多少? var num1 = 2; var num2 = 20; var num3 = num1-- + num2; var num4 = num1 + num2; console.log(num1 +