那些年面试官搞的“骚”操作!! 用一篇文章彻底搞懂++--
自增运算符在笔试的时候出现的概率很高,这种题目也很恶心,分析起来很废脑细胞,而且一旦有一步分析错误,结果就不对了。
下面给大家总结一些常见的题目,基本上覆盖了所有和单目运算符相关的题型。
做题目之前,先要弄懂前置和后置的区别,也许题目会很复杂,但基本原则是不会变的。
a++:执行a所在语句之后,a的值加1;
++a:执行a所在语句之前,a的值加1。
先来看一道入门题
#include <stdio.h>
int main()
{
int a = 1;
printf("a = %d\n", a++);
printf("a = %d\n", ++a);
return 0;
}
运行结果如下:
分析:
后置++先执行a所在语句,所以可以默认把++运算符去掉,于是,语句变成了输出整数a,只不过在语句运行结束后,记得还有个后置的++没有执行,a的值还要加1。于是结果就变成了输出1,但是a的值实际已经变成了2。
前置++先执行a加1操作,即a变成了3(2+1),最后再执行输出语句。所以结束是打印3。
难度加大一点
#include <stdio.h>
int main()
{
int a = 4;
a += a++;
printf("a = %d\n", a);
a = 4;
a += ++a;
printf("a = %d\n", a);
a = 4;
++a += a;
printf("a = %d\n", a);
a = 4;
++a += a++;
printf("a = %d\n", a);
a = 4;
++a += ++a;
printf("a = %d\n", a);
return 0;
}
注意:编译的时候,选择C++的编译器(g++)编译,C编译器不支持前置++作为左值!!
运行结果:
分析:
这个题目很多同学会急着把+=运算符展开,如果展开的话,结果就容易出问题。第一个,先不要管后置++,当作:
a += a;
a的值是8。但是后置++运算符是被我们默认去掉的,所以最后还得记得a加1,于是结果是9;
第二个,前置++,a先要加1,变成了5,5+5=10;
第三个,同第二个,都是前置++;
第四个,后置++先不要看,有一个前置++,执行a加1变成了5,5+5=10,最后再执行后置++操作,结果是11;
第五个,两个前置的++,于是a变成了6,结果6+6=12。
自增运算符结合逻辑运算符
#include <stdio.h>
int main()
{
int x = 1, y = 1;
if (x++ == 2 && ++y == 2)
{
printf("helloworld!\n");
}
printf("x = %d, y = %d\n", x, y);
return 0;
}
分析:
逻辑运算符具有短路原则,很多同学忽略了这一点。判断语句:
x++ == 2;
等价于:
x == 2; x = x + 1;
很显然判断不成立,但是此时x变成了2。逻辑运算符具有短路原则,所以:
++y == 2;
并不会执行!
再来一个升级版本
#include <stdio.h>
int main()
{
int x = 5, y = 6, z;
z = ++x + y++;
printf("x = %d, y = %d, z = %d\n", x, y, z);
x = 5, y = 6;
z = ++x + x++;
printf("x = %d, y = %d, z = %d\n", x, y, z);
x = 5, y = 6;
x = ++x + x++;
printf("x = %d, y = %d, z = %d\n", x, y, z);
x = 5, y = 6;
z = x > y ? ++x : y++;
printf("x = %d, y = %d, z = %d\n", x, y, z);
return 0;
}
Ubuntu运行结果:
Visual Studio 2012运行结果:
这个题目就比较恶心了,因为不同的编译器处理的结果还不一样。我们来看VS的结果吧,这个结果还比较符合常规思想。
第一个,等价于:
z = 6 + 6;
只是运算结束了,y的值还要再加1;
第二个,等价于:
z = 6 + 6;
只是运算结束了,x的值再加1;
第三个,等价于:
x = 6 + 6;
运算完成,x的值再加1,结果是13;
第四个,++x不会执行,执行y++,结果没有疑问。
最后再来一个终极装逼版
#include <stdio.h>
int main()
{
int i = 3, k;
k = (++i) + (++i) + (i++);
printf("i = %d, k = %d\n", i, k);
i = 3;
k = (++i) + (++i) + (++i);
printf("i = %d, k = %d\n", i, k);
i = 3;
k = (i++) + (i++) + (i++);
printf("i = %d, k = %d\n", i, k);
return 0;
}
Ubuntu运行结果:
Visual Studio 2012运行结果:
此时,我的心情是:
遇到这种笔试题,你可以鄙视他一下,扔掉考卷走人(想想就行,找工作要紧)! 这种题目不同的平台运行结果不同,如果不指定编译器,根本没有结果。 出这个题目的面试官可能自己也没有搞清楚,纯粹出于装逼的考虑。不看别的,就扫一眼这个代码,怎一个“骚”字了得。开发中谁没事写这样惨绝人寰代码?
继续分析!
第一个简单,先运算两次前置++,i变成了5,计算一次结果10;再运算10+5,结果为15,但是i还要再加1。(其实VS和Linux编译器过程不一样,这题只是个巧合)
第二个,Linux先运行两次前置++,i变成了5,进行一次计算5+5结果为10,然后再运算最后一个++i,i变成了6,于是结果为16;VS的过程是先进行三次前置++操作,结果不一样!
第三个,Linux等价于:
k = 3 + 4 + 5;//第一个i++,结果是3,但是i的值变成了4作为第二个i++初值
VS编译器等价于:
k = 3 + 3 + 3;
运算结束,i再加3次!
文章写完,键盘上又多了两根头发,笔试题确实比较费脑子!自增或者自减操作大家必须要把原理搞懂,这个才是最重要的。至于这些复杂的或者没有标准答案的题目,更多的是在考查大家对单目运算符的理解,多看多写多总结!
单目运算符还经常和指针结合,大家可以自己总结一下,对笔试有百利而无一害。
更多精彩视频、文章,关注 学益得智能硬件!