c语言和c++语言中的几种运算符
c与c++中的运算符种类繁多,虽然大多数都很简单,且用法明确。但是也有很多需要注意的地方。很早之前我就想将其中的一些注意点写下来了,但是总觉得每个点都很小,写一篇博客似乎篇幅太小了。今天一合计,不如就写一个关于运算符的合集吧。这篇博客里不会写的很详细,但是都是一些容易让人困惑的点。
i++ 与++i
i++
: 首先将i的值进行拷贝,然后将i值加1,最后返回拷贝;++i
: 首先将i值加1,然后返回i值;
由上述描述,我们会发现
i++
与++i
相比,除了返回值不同外,似乎还多进行了一个拷贝的操作,所以是否++i
的运行效率要高一些呢?答案是:是也不是。首先,在标准库里,编译器都会对这个额外的操作进行优化,因此二者其实性能一致。但是对于一些相对复杂的迭代器模型等还有用户自己重载的前置与后置的递增递减运算符,确实是有性能差距的,所以这种操作多了以后,性能差距就明显了。此处推荐尽量使用前置版本的递增递减运算符。
移位运算符
首先讲一下移位运算符。分别是>>(右移运算符)
与<<(左移运算符)
。
1.
首先需要说明的是如果移位运算符的操作对象是位数比较小的整形,比如说unsigned char
,在进行移位操作前,会先将其提升为整形(寄存器的位数,一般32位)。最后,表达式返回的也是一个整形(32位)的值。
移位运算符的操作对象为无符号数时,程序是可移植的。此时无论右移还是左移都是补零。
移位运算符的操作对象为有符号数时,此时程序是不可移植的。在不同的机器上有可能会出现不同的结果,其中有的机器上使用的是
逻辑移位
,也就是不考虑符号位,移位时另一边直接补零。还有一种是算术移位
(尽量保持只对无符号数进行移位操作)。注意:逻辑移位的话不需多讲,算术移位在做左移时其实与逻辑移位操作一样,但是它在右移时会在最高位补与符号位相同的值。移位运算符(包括重载的IO运算符),满足左结合律,且本身优先级不高不低。比算数运算符低,但比关系运算符、赋值运算符还有条件运算符优先级高。
运算符的求值顺序
我们都知道运算符有优先级、结合律还有求值顺序。这三者共同决定代码的确切执行。但是其中优先级与结合律都是比较清晰地,但是求值顺序这个属性一直不是很清晰。其实这是有原因的,很多运算符求值顺序都没有明确规定,据统计,明确规定了求值顺序的运算符只有4种运算符。
1.
逻辑与(&&)
:满足短路求值。a && b
首先判断a是否为true
,只有在a为true
的前提下才会对b进行求值,否则直接返回false
;
逻辑或(||)
:满足短路求值。a || b
首先判断a是否为false
,只有在a为false
的前提下才会对b进行求值,否则直接返回true
;条件(?:)运算符
:比如a? c:d
首先对a进行求值,当a为true
时,接下来对c进行求值;当a为false
时,接下来对d进行求值;逗号运算符(,)
:比如a=0,b=1;
首先对左侧表达式(a=0)进行求值,然后将求值结果(0)丢弃,对右侧表达式(b=1)进行求值,并返回右侧表达式的求值结果(1);
除法操作符(/)与取余操作符(%)
如果m与n是整数,并且n非0,则表达式
(m/n)*n+m%n
的结果与m相等。
表达式m/n
- 参与运算的m与n可以是任意实数,但n非0;
- 整数相除时所得结果还是整数,也就是说,若商中含有小数部分,直接丢弃,即向0取整。
表达式m%n
- 参与运算的m与n一定得是整数,且n不能等于0;
- 如果
m%n
的结果不为0,则其符号与m相同,与n无关,即m%(-n)等于m%n,(-m)%n等于-(m%n)
(此例中m与n都为正整数);
参考资料
- [1] C++ Primer(第5版)