操作符和表达式
C提供了所有你希望编程语言应该拥有的操作符,它甚至提供了一些你意想不到的操作符,比如三元操作符?:,正是因为它品种繁多的操作符,使得C语言很难精通。但是另一方面,C的许多操作符具有其他语言的操作符无法抗衡的价值。
移位操作符
对于左移操作符都是添0来补齐的,但是对右移操作符而言,特别是对于有符号的数据而言,使用逻辑移位(左边的位用0来填充)或者算术移位(左边的位用符号位来填充)由编译器决定。
赋值
对于表达式a=x=y+3;而言,说a等于x是不对的,比如如果x是int型的,而a是char型的,a就会把x截断。
复合赋值符
比如+=、-=,增加这些的意义为:K&R C设计者认为复合赋值符可以让程序员把代码写的更清楚一些。比如对于a[2*(y-6f(x))] = a[2(y-6f(x))] + 1,这样的式子可以写为a[2(y-6*f(x))] += 1,并且f的下标也只需访问一次,提高的速度。
单目操作符
单目运算符sizeof对于变量可以不加括号,对于类似int这样的类型,必须加上括号。
注意,对于++和—这样的前置或后置增值运算符,操作的是复制了该变量的一份拷贝而已。
逻辑操作符
这里比较帅的一个特性是短路求值short-circuited evaluation,工作原理如下,&&操作符的左操作数总是首先进行求值,如果它的结果为真,然后就紧接着对右操作符进行求值;但是,如果左操作数的值为假,那么右操作数便不再进行求值。对于||也是同理。
注意这里不要把逻辑操作符和位操作符搞混淆。逻辑操作符用于测试零值和非零值,而位操作符用于比较它们的操作数中对应的位。
条件操作符
expression1 ? expression2 : expression3:首先计算expression1,如果值为真,那么整个表达式的值就是expression2的值,expression3不会进行求值。但是如果expression1的值为假,那么整个语句的值就是expression3的值,expression2不会进行求值。
条件操作符也可以长生简洁的代码,并且可以产生较小的目标代码。
逗号操作符
逗号操作符将两个或多个表达式分割开来,这些表达式自左向右逐个进行求值,整个逗号表达式的值就是最后那个表达式的值。
下标引用、函数调用和结构成员
.和->操作符用于访问一个结构的成员,如果s是个结构变量,那么s.a就访问s中名叫a的成员;当你拥有一个指向结构的指针而不是结构本身,切欲访问它的成员时,就需要使用->操作符而不是.。
布尔值
C并不具备显式的布尔类型,所以使用整数来代替,其规则是:零是假,任何非零值均为真。但是,也并没有说1这个值比其他的非零值更真。所以对不是0的值最好不要进行比较哟。
左值和右值
左值就是那些能够出现在赋值符号左边的东西,右值就是那些可以出现在赋值符号右边的东西。
左值标示了一个可以存储结果值的地点;
右值指定了一个值;
所以,使用右值的地方可以使用左值,但是使用左值的地方不能使用右值。
*操作符:当它作为左值使用时,这个表达式就指定需要进行修改的位置,当它作为右值使用时,它就提取当前存储于这个位置的值。
表达式求值
C的整型算术运算总是至少以缺省整型类型的精度来计算,所以对于char a,b,c;c=a+b;其中的a、b、c都是按照int来计算的。OMG, 这个我还真是第一次知道。
操作符的属性
复杂表达式的求值顺序是由3个因素决定的:操作符的优先级、操作符的结合性以及操作符是否控制执行的顺序。
总结
- 有符号值的右移位操作是不可移植的;
- 在不同的用于表示布尔值的非零值之间不要比较;
- 不要编写结果依赖于求值顺序的表达式。