始之前,突然想到一个笑话。有个小伙子去面试的时候,技术没问题了,但是面试官故意各种刁难。最后在小伙子心灰意冷的时候,面试官蛋蛋一笑。“小伙子,你看你这么多问题都不会。摆明的技术不过关啊,不如先在公司里学习一段时间吧,月薪就给你2000怎样?” 卧槽,感情这tm都是坑我的啊?只能说,老哥,社会啊。所以说,基础知识不过关,被坑是常事呀~~~
那么,今天,就带大家看看C/C++里面究竟有多少不为人知的秘(keng)密(die)吧。可以测试一下,不看答案,自己能get到多少。
1
printf也风骚型
在此之前,先看一段简单得不能再简单的代码:
哎,这还不简单嘛?无非就是自增嘛,
第一个a输出1,第二个++a 输出2,
第三个a++用的原来的值再自增所以输出2。
蛋是!!!
一丝Q死迷???
自增没有错,坑就坑在,函数参数的入栈顺序是
从右往左
从右往左
从右往左
重要的事情说三遍,这就很好解释了。
先是a++,将a=1入栈,再自增。
而后++a,此时将a=3入栈,
最后输出自然是3 3 1。
2
编译器也偷懒型
Talk is cheap。Show me the code.
So,猜猜下面的代码输出结果是?
哎,这么简单的玩意儿,不是小瞧我胖虎嘛?
两个自增,绝逼是两个2啊。
呃,咱们run一下吧。
心里瞬间万头草泥马在奔腾啊
别急!
听老衲慢慢道来
在此之前,先复习一下&&和||运算符,
&&就是两个表达式为真最终结果才为真,
||是两个中只要有一个为真那么结果就为真。
于是乎,关于a++&&++a.
由于a初始为0,a++后自增,先把值拿来用了在让a+1。
所以整个表达式可以看作是0&&2,
但是编译器坑爹啊,他读到0,然后发现,这是一个&&操作。
有一个都是假了那最后结果肯定也是假的,
没必要做后面的运算了。
所以,++a那一句编译器并不会再去理会,
最终的结果是,a只自增了一次。
对于||操作,道理也是一样的。
当他发现||左边的表达式为真(非0)时,
后面的编译器不在理会。这点大家记住。
3
当switch没有了break
switch case语句是一个很神奇的东西,
我也是近来才了解原来他还有这种操作。
在写switch case语句的时候,
我们被要求每一条语句都写上break。
但是实际开发中,
往往会有那么几个人由于疏漏忘了写break子句导致莫名的结果错误。
下面我们来看看没有了break的
switch语句
是有多风骚
嗯,这次就不再用++来玩大家了
运行结果:
之前我一直以为,就算没有break
后面的语句也只会在符合条件的情况下
才会执行。
然而,是我想错了。
上网查了一下,switch语句设计的初衷
就有着一种贯穿的思想
说白了 就是,符合某个case分支以后
如果没有break
那么后面的case 子句无论如何都会执行
所以,你如果只想执行一个条件
别忘了在每个分支后面写上break
4
关于声明和定义,你知多少
下面代码是在C平台上运行的。C++不允许这么干了。
那么,你觉得下面的代码C编译器会报错吗?
答案是不会!
再看:这个会报错吗?
答案,YES!
这就很扎心了,两段代码,位置不一样,还出错了???
嗯,这里就要讲讲声明和定义的区别了。
第一个程序int a是写在全局变量区的,
那么对于全局变量,
声明+赋值=定义
也就是之前无论我们int a多少次
只要没有赋值,
那么编译器就会默认我们这是一条声明。
声明嘛,你想声明多少次都行。
如果都是声明没有赋值,那么编译器就会默认
最后一条声明为定义。
说白了就是,
声明可以有多个,但是定义只能有一个
而第二个程序就不同了,
由于int a 是写在局部变量区域,
对于局部变量来说,无论是否赋值都是定义
所以这里编译器会给出一个重定义的CE。
5
static原来是这样
关于static可以说的实在太多了,但是今天只说一点。
也是各位新手朋友经常犯的。
先看代码:
可以预测一下输出结果嘛
将变量声明为static以后,
该变量会放在全局静态区。
那么这个区域的变量有几个特点
会在程序刚开始运行时就完成初始化,
也是唯一的一次初始化
如果没有初始化,编译器默认初始化为0
于是乎,由于上述程序num只初始化了一次,
所以在后面的9次test()函数的调用中,
static int num = 10
这条语句不会在执行。
因此才会有上面的输出的输出结果
6
printf继续风骚型
关于printf的输出,也是面试官们经常拿来玩的一个埂,通过这个可以看出你对基础知识的把握程度。
先看代码:
输出多少?
看结果:
为什么会出现这个情况呢?
这是因为,printf输出的时候,
并不会去判断变量的类型,
他很听话,只会按照你给的格式控制符去内存中解析数据然后输出
比如整数在内存中是以补码的形式存在的。
(关于源码补码知识不在赘述,读者可自行上网了解)
-1的补码就是32个1。
那么32个1,按照有符号整数来解析就是-1
按照无符号来解析就是上面的结果。等等。
今天就先写到这吧,C/C++还有很多值得大家注意的地方,比如C的宏函数带来的运算级问题,结构体对齐等等,const和指针引发的一系列血案等等。咱们下次有空再聊。