C运算符优先级的错误
1. 优先级运算符的使用
我相信玩过C的人都曾有过这样的或那样的不可思议经历,会非常感慨C的博大精深、深不可测,很多时候你根本不知道一条语句的真实执行情况(除非经过具体环境的编译和执行得出结论,可能你事后还是很迷茫),其实,有些已成事实特性并不是原本设计C语言时想要看到的,因为有些运算符的优先级是错误的,如果你不相信,下面就来看一下这样例子:
i = 1, 2;
你觉得i的结果会是多少?我们知道逗号的运算符的值就是最右边操作数的值。但在这里赋值符的优先级更高,所以实际情况应该是:
(i = 1), 2; /* i的值为1 */
i负值为1,然后执行常量2的运算,计算结果丢弃。最终i的结果是1而不是2。
2.常见的最容易犯错的优先级运算符
1)"."的优先级高于"*"
举例:*p.f
可能误以为的结果:p所指对象的字段f,(*p).f
实际结果:对p取f偏移,作为指针,然后进行解除引用的操作 *(p.f)
2) "[]"的优先级高于"*"
举例:int *ap[]
可能误以为的结果:ap是一个指向int数组的指针 int(*ap)[]
实际结果:ap是一个元素为int指针的数组 int *(ap[])
3) 函数"()"的优先级高于"*"
举例:int *fp()
可能误以为的结果:fp是一个函数指针,所指函数返回int,int (*fp)()
实际结果:fp是一个函数,返回类型int *,int *(fp())
4) "=="和"!="的优先级高于位操作符
举例:(val & mask != 0)
可能误以为的结果:(val & mask) != 0
实际结果:val & (mask != 0)
5) "=="和"!="的优先级高于赋值符
举例:c = getchar() != EOF
可能误以为的结果:(c = getchar()) != EOF
实际结果:c = (getchar() != EOF)
6) 算术运算符优先级高于移位运算符
举例:msb << 4 +lsb
可能误以为的结果:(msb << 4) +lsb
实际结果:msb << (4 +lsb)
7) 逗号运算符优先级低于所有其他运算符
举例:i = 1, 2
可能误以为的结果:i = (1, 2)
实际结果:(i = 1), 2
对于这些运算符的大部分,如果坐下来好好想想就能变得明了,但是像第'7)'种可能会让很多程序员痛心疾首。所以在表达式中如果有布尔操作、算术运算、位操作等混合运算,你最好应该在适当的地方加上括号,只是清楚明了,事实证明这是一个良好的变成风格。
3. 操作符的结合性
操作符优先级用来决定不含括号的表达式中操作数之间的“紧密”程度,如果具有相同的优先级的操作符出现,那操作符的结核性就开始发挥作用了。
举例:int a, b = 1, c = 2;
a = b = c;
对于这个实例,如果先执行"b = c",a的结果为2,如果先执行"a=b",a的结果为1。事实上所有的赋值符(包括符合赋值符)都是右结合性,因此这里的a的结果为2。
类似地,具有左结合性的操作符是从左向右依次执行,如位操作符"&"和"|"。结合性用于表达式中两个以上的相同的优先级的操作符的情况,事实上所有的优先级相同的操作符,他们的结合性也是相同的。
4.总结
在C语言中,跟顺序有关的问题,有些定义很好,如优先级和结合性,有些定义的很含糊,如大部分表达式中的各个操作数计算顺序就是不确定的,他的目的是为了让编译器设计者选择最合适的方法来产生最快的代码。但是要注意的是在函数调用中,各个参数的计算顺序是不确定的。
补充:软件开发 , C语言 ,