脚本宝典收集整理的这篇文章主要介绍了C++实践:运算符优先级“错误”,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
运算符是基本的语言元素,虽然接触编程语言的年岁不短了,但有时面对着一些表达式,仍不能立马确认运算顺序。我相信很多人也有我这方面的疑惑,今天就把一些“设计错误”的运算符拉出来溜溜。
& 和 |
看下面的代码片段,变量a
的值是多少呢?
int a = 1 | 0 == 1 & 0;
对于表达式1 | 0 == 1 & 0
,包含三个运算符,已知&
优先级高于|
,并且这些位操作符要么高于==
,要么低于==
,分两种情况讨论:
- 位操作符优先级高于
==
等价于(1 | 0) == (1 & 0)
,计算的结果为0
。
-
==
优先级高于位操作符
等价于1 | ((0 == 1) & 0))
,计算的结果为1
。
将上面的代码运行打印会得到a
的值为1。这说明==
优先级高于位操作符。这或许是我最迷惑的运算符规则了,在我看来位操作符本质上是算术运算符,都是产生一个数,应该跟算术运算符的规则大体一致。故而,我认为第一种更合理。
是不是设计的错误呢,终于在《C专家编程》这本书里找到了答案,即下节。
'And' and 'AND' or 'Or' or 'OR'
&&
、||
操作符与 ==
操作符的优先级关系问题是这样产生的。在 C 的早期,&
和 &&
合用同一个操作符, |
和 ||
也是如此(明白吗?)。 它继承了 B 和 BCPL 中的概念“真值上下文”。就是在 if
和 while
等后面需要一个布尔值的时候,&
和 丨
就被翻译成现在的 &&
和 ||
。如果它们在一般的表达式里,就被解释成位操作符,也就是现在的样子。这个机制操作起来没有问题,但理解起来很困难(在真值上下文里,存在“顶层运算符”的概念)。&
和 |
的优先级跟现在一样。最初,在 Alan Snyder 的催促下,我在C语言中加入了 &&
和 ||
操作符。这就成功地把位运算的概念和布尔运算的概念分了开来。然而,我心怀不安,因为我意识到了优先级的问题。例如,在现存的大量程序中,存在诸如这样的表达式: if(a == b & c == d)
。
事后回想,如果我们一开始就改变优先级,让&
的优先级高于==
,在逻辑上可能更清晰一些。但是,从安全的角度出度,只能做到把 &
和 &&
分开这个程度,无法在两者的优先级之间再插入其他的操作符(否則的话,现有的大量代码都有可能出问題)。
从上面的描述可以看出,最终设计的结果在于代码兼容性上的考量。Java
和 C#
的操作符优先级跟C/C++
大同小异,这可以认为是另一个层次的兼容:程序员的编码习惯。
C++其他不合理的操作符
在《C专家编程》这本书里还列出了其他错误的操作符,这里一并列出:
优先级问题
表达式
人们可能误以为的结果
实际结果
.的优先级高于*。->优先级用于消除这个问题
*p.f
p所指对象的字段f。 (*p).f
对p取f偏移,作为指针,然后进行间接引用操作。*(p.f)
[]高于*
int *ap[]
ap是个指向int数组的指针。int(*ap)[]
ap是个元素为int指针的数组。int *(ap[])
函数()高于*
int *fp()
fp是个函数指针,所指函数返回int。int (*fp)()
fp是个函数,返回int。int(fp())
==和!=高于位操作符
(val & mask != 0)
(val & mask)!= 0
val & (mask != 0)
==和!=高于赋值符
c=getchar()!=EOF
(c=getchar())!=EOF
c=(getchar()!=EOF)
算术运算符高于移位运算符
msb << 4 + lsb
(msb << 4) + lsb
msb << (4 + lsb)
逗号运算符在所有运算符中优先级最低
i=1,2
i=(1,2)
(i=1),2
这些不合理的操作符毕竟占了少数,遇到它们完全可以使用括号保证可靠性,同时不会影响代码的可读性。
订阅最新的文章请关注我的公众号:
以上是脚本宝典为你收集整理的C++实践:运算符优先级“错误”全部内容,希望文章能够帮你解决C++实践:运算符优先级“错误”所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。