为了账号安全,请及时绑定邮箱和手机立即绑定

算子优先与评价顺序

算子优先与评价顺序

C++ C
慕莱坞森 2019-07-02 10:57:43
算子优先与评价顺序术语“运算符优先”和“评估顺序”是编程中非常常用的术语,对于程序员来说非常重要。据我所知,这两个概念是紧密联系在一起的;在谈论表达时,一个概念离不开另一个概念。让我们举一个简单的例子:int a=1;  // Line 1a = a++ + ++a;  // Line 2printf("%d",a);  // Line 3现在,很明显Line 2导致未定义的行为,因为C和C+中的序列点包括:在计算&(逻辑和)、欧元(逻辑OR)和逗号运算符的左操作数和右操作数之间。例如,在表达式中*p++ != 0 && *q++ != 0,子表达式的所有副作用*p++ != 0在尝试访问之前已完成。q.在计算三元“问号”运算符的第一个操作数和第二个或第三个操作数之间。例如,在表达式中a = (*p++) ? (*p++)  : 0之后有一个序列点。*p++,这意味着在执行第二个实例时,它已经增加了。在一个完整表达式的结尾。此类别包括表达式语句(例如赋值)。a=b;)、返回语句、if、Switch、while或do-while语句的控制表达式以及for语句中的所有三个表达式。在函数调用中输入函数之前。未指定计算参数的顺序,但此顺序点意味着在输入函数之前,它们的所有副作用都已完成。在表达中f(i++) + g(j++) + h(k++), f的原始值的参数调用。i,但是i在进入f..同样,j和k在输入前更新g和h分别。但是,它没有按哪个顺序指定。f(), g(), h()被执行,也不按哪个顺序执行i, j, k都是递增的。的价值j和k在…的身体里f因此是没有定义的。3注意,函数调用f(a,b,c)的逗号运算符和计算顺序的使用。a, b,和c没有具体说明。在函数返回时,将返回值复制到调用上下文中。(这个序列点仅在C+标准中指定;它仅隐式地存在于C中。)在初始化器的末尾;例如,在声明中计算5之后int a = 5;.因此,通过第3点:在一个完整表达式的结尾。此类别包括表达式语句(例如赋值a=b;)、返回语句、if、Switch、while或do-while语句的控制表达式,以及for语句中的所有三个表达式。Line 2显然会导致行为不明。这说明了未定义行为紧密耦合序列点.现在让我们再举一个例子:int x=10,y=1,z=2; // Line 4int result = x<y<z; // Line 5现在很明显Line 5将使变量result商店1.现在表达x<y<z在……里面Line 5可将其评价为:x<(y<z)或(x<y)<z..在第一种情况下,result将是0在第二种情况下result将是1..但我们知道,当Operator Precedence是Equal/Same - Associativity因此,被评估为(x<y)<z.这就是我们所说的MSDN条款:C算子的优先级和结合性影响表达式中操作数的分组和求值。只有当其他优先级较高或较低的运算符存在时,运算符的优先级才是有意义的。首先计算具有高优先级运算符的表达式。优先级也可以用“绑定”一词来描述。具有较高优先级的运算符据说具有更紧密的绑定。现在,关于上面的文章:它提到“先计算具有较高优先级运算符的表达式”。这听起来可能不正确。但是,如果我们考虑到这一点的话,我认为这篇文章并没有说错什么。()也是运算符。x<y<z同(x<y)<z..我的推理是,如果联想性不起作用,那么整个表达式的评估就会变得模棱两可,因为<不是序列点.另外,我发现的另一个链接是这样的算子优先性与结合性:此页面按优先级(从最高到最低)列出C运算符。它们的结合性指示在表达式中应用优先级相等的操作符的顺序。以第二个例子为例int result=x<y<z,我们可以在这里看到这三个表达式,x, y和z因为,表达式的最简单形式是由单个文字常量或对象组成。因此,表达式的结果x, y, z会在那里r值,即10, 1和2分别。因此,现在我们可以解释x<y<z如10<1<2.现在,由于我们有两个表达式要计算,所以不起作用吗?10<1或1<2既然运算符的优先级是一样的,它们从左到右被评估。?以最后一个例子作为我的论点:int myval = ( printf("Operator\n"), printf("Precedence\n"), printf("vs\n"),printf("Order of Evaluation\n") );在上面的示例中,由于comma运算符具有相同的优先级,则计算表达式。left-to-right的返回值printf()存储在myval.在……里面SO/IEC 9899:201X在……下面J.1未指明的行为它提到
查看完整描述

3 回答

?
撒科打诨

TA贡献1934条经验 获得超2个赞

优先级影响计算顺序的唯一方法是创建依赖关系;否则,两者是正交的。您已经仔细选择了一些琐碎的示例,在这些示例中,由优先级创建的依赖关系最终确实完全定义了计算顺序,但这通常不是真的。不要忘记,许多表达式有两种效果:它们产生值,也有副作用。这两种情况不需要一起发生,所以即使依赖关系强制执行特定的计算顺序,这也只是值的求值顺序;它对副作用没有影响。


查看完整回答
反对 回复 2019-07-02
?
哈士奇WWW

TA贡献1799条经验 获得超6个赞

查看这一点的一个好方法是获取表达式树。

如果你有一个表达式,让我们说x+y*z您可以将其重写为表达式树:

应用优先级和关联规则:

x + ( y * z )

在应用优先级和关联规则之后,您可以安全地忘记它们。

以树的形式:

  x+
    y  *
    z

现在这个表达式的叶子是xyz..这意味着你可以评估xyz按您想要的任何顺序,这也意味着您可以评估*x任何顺序。

既然这些表情没有副作用,你就不在乎了。但是,如果它们这样做了,排序可能会更改结果,而且由于排序可以是编译器决定的任何内容,所以您有一个问题。

现在,序列点给这种混乱带来了一点秩序。他们有效地把这棵树切成几段。

x + y * z, z = 10, x + y * z

优先性和结合性之后

x + ( y * z ) , z = 10, x + ( y * z)

树:

      x    +
        y      *
        z  , ------------
      z    =
      10     
  , ------------
      x    +
        y      *
        z

树的顶部将在中间之前进行评估,中间部分在底部之前进行评估。


查看完整回答
反对 回复 2019-07-02
  • 3 回答
  • 0 关注
  • 464 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信