谁定义了C运算符precedence和关联性? [英] Who defines C operator precedence and associativity?

查看:958
本文介绍了谁定义了C运算符precedence和关联性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简介

在对C / C ++教材每次,你会发现一个运营商precedence和关联表如下所示:

<一个href=\"http://en.cp$p$pference.com/w/cpp/language/operator_$p$pcedence\">http://en.cp$p$pference.com/w/cpp/language/operator_$p$pcedence

一个计算器上问的问题是这样的:

什么顺序如下功能执行:

F1()* F2()+ F3(); 结果
F1()+ F2()* F3();

谈到previous图我自信地回答说,职能左到右联,以便在previous语句在这两种情况下这样的评价:


  

F1() - > F2() - > F3()


在函数求你完成这样的评价:


  

(A1 * A2)+ A3结果
  A1 +(A2 * A3)


要我吃惊的是,很多人告诉我,我是平掉错了。决心要证明他们是错的,我决定转向ANSI C11标准。我再一次惊讶地发现,很少是运营商precedence和结合提及。

问题


  1. 如果我的信念,功能总是由左到右的评估是错的,什么是表指的是函数precedence和关联性究竟意味着什么?

  2. 谁定义了operator precedence和关联性,如果它不是ANSI?如果是ANSI谁做的定义,为什么很少提及运营商precedence和关联性?是运营商precedence和关联从ANSI C标准的推断或者是它的数学定义?


解决方案

操作precedence在适当的标准定义。 C和C ++的标准是,究竟C和C ++是一个真正的定义。所以,如果你仔细观察,细节都在那里。其实,细节都在语言的语法的。例如,看看语法生产规则 + - 在C ++(统称的添加剂-ex pressions 的):

 添加剂-EX pression:
  乘-EX pression
  添加剂-EX pression +乘法-EX pression
  添加剂-EX pression - 乘-EX pression

正如你所看到的,乘-EX pression 的是一个的添加剂-EX pression 的子规则。这意味着,如果您有类似 X + Y * Z Ÿ* Z 前pression是 X + Y * Z 的SUBEX pression。这定义了这两个运营商之间的 precedence

我们还可以看到一个的添加剂-EX pression的左操作数的扩展到其他的添加剂-EX pression 的,这意味着用 X + Y + Z X + Y 是它的一个SUBEX pression。这个定义的关联

关联性确定如何同一运营商的相邻用途将进行分组。例如, + 是左到右的关联,这意味着 X + Y + Z 将像分组这样:(X + Y)+ Z

请不要误会这个评估顺序即可。我们绝对没有理由以Z 的价值不能在 X + Y来计算是。重要的是,它是 X + Y 的计算,而不是 Y + Z

有关函数调用操作符,左到右联是 F()()(可如果发生˚F返回的函数指针,例如)进行分组,像这样:(F())()(当然,其他方向也没有任何意义)。

现在让我们考虑你要找的例子:

  F1()+ F2()* F3()

* 运营商具有较高的precedence比 + 运营商,所以前pressions分组像这样:

  F1()+(F2()* F3())

我们甚至不须考虑相关性,因为我们没有任何同一个运营商的彼此相邻。

的功能评价致电离pressions是,然而,完全unsequenced。没有理由 F3 不能先调用,那么 F1 ,然后 F2 。在这种情况下,唯一的要求是操作者的操作数之前的操作者进行评估。因此,这将意味着 F2 F3 的前作 * 评估和 * 必须进行评估和 F1 之前必须叫 + 进行评估。

一些运营商这样做,不过,强加给他们的操作数的计算测序。例如,在 X ||是 X 总是前评估。这使得短路,其中不需要,如果 X 来评估已经知道是真正

评估的顺序是C和C pviously ++中定义与使用的序列点的$ P $,并且都已经改变的术语在测序来定义的东西之前,的关系。欲了解更多信息,请参见未定义行为和序列点

Introduction

In every textbook on C/C++, you'll find an operator precedence and associativity table such as the following:

http://en.cppreference.com/w/cpp/language/operator_precedence

One of the questions on StackOverflow asked something like this:

What order do the following functions execute:

f1() * f2() + f3();
f1() + f2() * f3();

Referring to the previous chart I confidently replied that functions have left-to-right associativity so in the previous statements the are evaluated like this in both cases:

f1() -> f2() -> f3()

After the functions are evaluated you finish the evaluation like this:

(a1 * a2) + a3
a1 + (a2 * a3)

To my surprise, many people told me I was flat out wrong. Determined to prove them wrong, I decided to turn to the ANSI C11 standard. I was once again surprised to find out that very little is mentioned on operator precedence and associativity.

Questions

  1. If my belief that functions are always evaluated from left-to-right is wrong, what does the table referring to function precedence and associativity really mean?
  2. Who defines operator precedence and associativity if it's not ANSI? If it is ANSI who makes the definition, why is little mentioned about operator precedence and associativity? Is operator precedence and associativity inferred from the ANSI C standard or is it defined in Mathematics?

解决方案

Operator precedence is defined in the appropriate standard. The standards for C and C++ are the One True Definition of what exactly C and C++ are. So if you look closely, the details are there. In fact, the details are in the grammar of the language. For example, take a look at the grammar production rule for + and - in C++ (collectively, additive-expressions):

additive-expression:
  multiplicative-expression
  additive-expression + multiplicative-expression
  additive-expression - multiplicative-expression

As you can see, a multiplicative-expression is a subrule of an additive-expression. This means that if you have something like x + y * z, the y * z expression is a subexpression of x + y * z. This defines the precedence between these two operators.

We can also see that the left operand of an additive-expression expands to another additive-expression, which means that with x + y + z, x + y is a subexpression of it. This defines the associativity.

Associativity determines how adjacent uses of the same operator will be grouped. For example, + is left-to-right associative, which means that x + y + z will be grouped like so: (x + y) + z.

Don't mistake this for order of evaluation. There is absolutely no reason why the value of z could not be computed before x + y is. What matters is that it is x + y that is computed and not y + z.

For the function call operator, left-to-right associativity means that f()() (which could happen if f returned a function pointer, for example) is grouped like so: (f())() (of course, the other direction wouldn't make any sense).

Now let's consider the example you were looking at:

f1() + f2() * f3()

The * operator has higher precedence than the + operator, so the expressions are grouped like so:

f1() + (f2() * f3())

We don't even have to consider associativity here, because we don't have any of the same operator adjacent to each other.

Evaluation of the functions call expressions is, however, completely unsequenced. There's no reason f3 couldn't be called first, then f1, and then f2. The only requirement in this case is that operands of an operator are evaluated before the operator is. So that would mean f2 and f3 have to be called before the * is evaluated and the * must be evaluated and f1 must be called before the + is evaluated.

Some operators do, however, impose a sequencing on the evaluation of their operands. For example, in x || y, x is always evaluated before y. This allows for short-circuiting, where y does not need to be evaluated if x is known already to be true.

The order of evaluation was previously defined in C and C++ with the use of sequence points, and both have changed terminology to define things in terms of a sequenced before relationship. For more information, see Undefined Behaviour and Sequence Points.

这篇关于谁定义了C运算符precedence和关联性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆