经典面试题:i++和++i
写出下面代码执行后i , j , m , n 的值:
int i = 10 , j = 10;
int m = (i++) + (i++) + (i++) ;
int n = (++j) + (++j) + (++j);
分析:本题考查算数运算符中的++,而且区分++在前和++在后的两种情况。
++在前: ++a <=> 先自加,再赋值
++在后: a++ <=> 先赋值,再自加
特别地:如果++a或者a++自成一条语句,都视作 a = a + 1。
回到本题:
int m = (i++) + (i++) + (i++) ; //i++先赋值,后自加
由于++在后,所以先赋值,后自加。
但是不同的编译器得到的结果也不同
For:GCC编译器
- 第一次(i++)时,i = 10 ,所以赋值为10 , 赋值完成后i自加1,此时i = 11.
- 第二次(i++)时, i = 11 , 所以赋值11 ,复制完成后i再次自加1, 此时i = 12.
- 第三次(i++)时, i = 12 , 所以赋值为12 , 赋值完成后i再次自加1,此时i = 13.
所以经过本次运算后,m的值为:10 + 11 + 12 = 33.
For:VS编译器
先执行加法操作,再执行自加,而且是左右加法操作执行完毕后,才执行三次自加操作
- 第一次(i++)、第二次(i++)、第三次(i++)都赋值10,最后再进行三次自加
所以经过本次运算后,m的值为:10 + 10 + 10 = 30.
接下来分析++j
int n = (++j) + (++j) + (++j);
++在前,所以先自加,再赋值。
同样的,不同的编译器得到的结果也不同的
For:GCC编译器
在GCC编译器中,只要攒够两个完整的操作数,就会执行加法或减法操作。
所以在进行了两次(++j)时,已经出现了两个操作数。
但是:此时的(++j)已经等于12了,所以编译器在进行两个操作数相加的时候其实是下面这样的:
两次次自加结束后,进行中间的一次加法运算. 此时(++j)=12,所以编译器会对 int n = (++j) + (++j) ;
这个表达式进行转换: int n = 12 + 12; [=24]
- 第一次(++j):此时先自加,所以赋值为10+1 = 11,
- 第二次(++j):此时先自加,所以赋值为11+1 = 12,取第二次的运算结果作为自加结果 <=>前两次的运算结果都是12
- 攒够了两个操作数,所以执行加法运算:12 + 12 = 24
- 第三次(++j):先自加,所以赋值为12+1 = 13
- 又攒够了两个操作数,所以执行加法运算,所以最终的结果为:24 + 13 = 37
所以经过本次运算后,m的值为:12 + 12 + 13 = 37.
For:VS编译器
int n = (++j) + (++j) + (++j);
vs编译器在执行上面这个表达式时,它的执行顺序如下图所示:
它会先执行三次自加操作,再进行加法操作。
- 第一次(++j):j = 10+1 = 11
- 第二次(++j):j = 11+1 = 12
- 第三次(++j):j = 12+1 = 13
然后三次自加结束后,进行中间的两次加法运算. 此时(++j)=13,所以编译器会对 int n = (++j) + (++j) + (++j);
这个表达式进行转换: int n = 13 + 13 + 13; [=39]
所以VS编译器 得到的结果是m的值为:13 + 13 + 13 = 39.