C中的哪个运算符具有错误的优先级?

时间:2019-02-17 13:07:13

标签: c operators operator-precedence

在K&R C(2E)的“简介” 部分中,有以下段落:

  与其他语言一样,

C也有其缺陷。一些运算符的优先级有误; ...

这些是哪个运算符?他们的优先级有何错误?

this是其中一种情况吗?

4 个答案:

答案 0 :(得分:9)

是的,您链接到的消息中讨论的情况是使用C运算符优先的主要问题。

从历史上看,C的开发没有&&。为了执行逻辑AND操作,人们将使用按位AND,因此a==b AND c==d将用a==b & c==d表示。为此,==的优先级高于&。尽管后来在语言中添加了&&,但&的优先级仍然低于==

通常,人们喜欢写(x&y) == 1之类的表达式要比x & (y==1)更为频繁。因此,如果&的优先级比==高,那就更好了。因此,人们对C运算符优先级的这一方面不满意。

这通常适用于&^|的优先级低于==!=<,{{1 }},><=

答案 1 :(得分:4)

有一个明确的优先权规则是无可争议的。 规则是如此明确,以至于强类型系统(例如Pascal),错误的优先级将在编译时给出明确的语法错误。 C的问题在于,由于其类型系统是自由放任的,因此错误证明是更多的逻辑错误,导致错误而不是在编译时可捕获的错误。

规则

让○□成为两个类型的运算符

○:α×α→β
□:β×β→γ
和α和γ是不同的类型。

然后

x○y□z可以仅表示(x○y)□z,且具有类型分配
x:α,y:α,z:β

而x○(y□z)将是类型错误,因为○只能取一个α,而右边的子表达式只能产生一个非α的γ。

现在让我们

将此应用到C

在大多数情况下,C都能正确处理

(==):数字×数字→布尔值
(&&):布尔值×布尔值→布尔值

so &&应该在==以下并且是

类似

(+):数字×数字→数字
(==):数字×数字→布尔值

,因此(+)必须高于(==),这再次正确

但是对于按位运算符

&/ |的两个位模式(又称为数字)产生一个数字 即
(&),(|):数字×数字→数字
(==):数字×数字→布尔值

因此是典型的掩码查询,例如。 x & 0x777 == 0x777
只有将(&)视为算术运算符,即(==)以上,才有意义-

C鉴于上述类型规则,将其置于错误的下方

我当然已经在数学/类型推断方面表达了以上观点

在更实用的C术语中,x & 0x777 == 0x777自然地分为 x & (0x777 == 0x777)(在无显式括号的情况下)

这样的分组何时可以合法使用?
我(个人)不相信有任何

IOW Dennis Ritchie对这些优先顺序是错误的非正式声明可以给予更正式的理由

答案 2 :(得分:1)

错误听起来可能太刺耳了。普通人通常只关心诸如+-*/^之类的基本运算符,如果这些运算符不能像他们的数学编写方式那样工作,则可能称为 错误 。幸运的是,这些在C语言中是“有序的”(除了不存在的幂运算符)

但是,有些其他运营商可能无法像许多人期望的那样工作。例如,按位运算符的优先级低于比较运算符,后者已经由Eric Postpischil提到。这虽然不太方便,但仍然不是很“错误”,因为以前没有为它们定义任何标准。它们是上个世纪计算机诞生时发明的。

另一个示例是移位运算符 << >>,其优先级低于+-。移位被认为是乘法和除法,因此人们可能希望移位应该比+-更高。编写x << a + b可能会使许多人认为它是 x * 2 a + b ,直到他们查看优先级表为止。除了(x << 2) + (x << 4) + (y << 6)之外,不如没有括号的简单加法


在其他语言中,有很多“错误”优先级的真实示例

答案 3 :(得分:0)

这取决于哪个优先顺序约定被视为“正确”。没有任何物理法则(或土地法则)要求优先级一定。它是随着时间的流逝而发展的。

在数学中,运算符优先级通常被视为“ BODMAS”(括号,阶,除,乘,加,减)。括号放在首位,减号放在最后。Ordering Mathematical Operations | BODMAS Order of operations

编程中的运算符优先级需要更多的规则,因为运算符更多,但是您可以弄清楚它与BODMAS的比较方式。

此处显示了ANSI C优先级方案: https://en.cppreference.com/w/c/language/operator_precedence

正如您所看到的,一元加法和减法处于2级-高于乘法和除法处于3级。这可能会使数学家在表面上阅读时感到困惑,因为后缀/后缀的递增和递减优先。 >

在这种情况下,始终值得考虑在数学代码中添加括号(即使在语法上不必要的地方),以确保向人类读者清楚您的意图。通过这样做,您将一无所获(尽管您可能会被一个严格的代码审查员激怒了,您可以在其中审查有关代码风险管理的内容)。您可能会失去可读性,但是在调试时,意图总是更加重要。

是的,您提供的链接就是一个很好的例子。由此导致无数昂贵的生产错误。