【问题标题】:Comma(,) operator suppress the precedence of parentheses in CComma(,) 运算符抑制 C 中括号的优先级
【发布时间】:2018-07-09 13:20:25
【问题描述】:

我刚开始读C。

情况:

x = ( y = 3, ( z = ++y + 2 ) + 5 )

它首先评估 y = 3 然后评估 ( z = ++y + 2 )

我的问题:

它应该首先计算 ( z = ++y + 2 ),因为逗号(,) 的优先级远低于括号

我的思维方式:

  1. 由于优先级,我们选择外括号

  2. 那么我们需要计算括号

  3. 在这个(括号)下我再次开始应用优先规则

  4. 所以我先拿内括号来评估

附注:

这不是重复的

我已经浏览了这些链接,但仍然无法理解

Behavior of comma operator in C

C comma operator

What does the comma operator , do?

https://docs.microsoft.com/en-us/cpp/cpp/comma-operator

Uses of C comma operator

https://en.wikipedia.org/wiki/Comma_operator

【问题讨论】:

  • 您需要有人审查您的代码。不要单独编码。
  • , 从左到右计算,左边的参数必须在右边之前计算。我看不出作为右侧子表达式的括号的优先级在这里有什么意义。 (确实,这段代码很糟糕。)
  • @Bhaskar :运算符优先级规则使x = ( y = 3, ( z = ++y + 2 ) + 5 ) 等同于x = ((y = 3), ((z = ((++y) + 2)) + 5))。不多也不少。
  • @Bhaskar 这是一个你需要解释才能通过你的课程的作业吗?如果不是,就忽略它,把这个表达扔掉,不要在这个地球上浪费你有限的时间来试图理解它。你永远不会在真正的程序中遇到这样的代码。你永远不会想写这样的代码。我是我认识的最有经验的 C 程序员之一,我懒得花我有限的时间在这个地球上试图理解那个表达式。出于所有意图和目的,它毫无意义。
  • 运算符的优先级仅说明操作数和子表达式如何与运算符相关联,而不是它们的求值顺序。优先级表示逗号连接了我在之前的评论中列出的两个子表达式。举个更简单的例子,a*b+c*d 中运算符的优先级仅说明操作数被分组为(a*b)+(c*d),它不说明a*bc*d 的评估顺序。它们可以按任何顺序进行评估,因为+ 不强制执行顺序。另一方面,逗号运算符需要评估顺序。

标签: c


【解决方案1】:

您将运算符优先级与评估顺序混淆了。

运算符优先级决定子表达式的分组方式。它规定何时评估每个操作数。

逗号运算符在其左操作数和右操作数之间有一个序列点。在y = 3, ( z = ++y + 2 ) + 5 的情况下,这意味着y = 3 必须在之前被完全评估。( z = ++y + 2 ) + 5 可以被评估。

还要注意在子表达式( z = ++y + 2 ) + 5 中,不能保证括号内的所有内容都在括号内的所有内容之前进行评估。你只知道( z = ++y + 2 )5( z = ++y + 2 ) + 5 被评估之前被评估。例如,如果您有(z = ++y + 2) + y,这将调用undefined behavior,因为可以在++y 的副作用之前或之后评估第二个y

作为另一个示例,如果您有 x = (func1() + 3) + func2(),则可以先调用 func1,或者先调用 func2,因为未指定操作数的求值顺序。如果这两个函数都修改了同一个全局变量,您将无法可靠地知道该变量的值。

【讨论】:

  • "sequence point": OP 甚至幸运的是有一个,否则我们会因为对相同数据的多次未排序读取/写入而产生 UB...
【解决方案2】:

优先级和评估顺序是不同的东西。在表达式(a*b) - (c+d) 中,编译器可以在(a*b) 之前计算(c+d),即使乘法的优先级高于加法。但是在表达式a,b和代码a;b中,需要编译器在b的计算之前对a的计算进行排序。

【讨论】:

    【解决方案3】:

    您对优先级评估顺序感到困惑。优先级是将不同类型的运算符及其操作数分组的优先级。

    逗号(,) 运算符构成Sequence Point,因此保证其操作数的特定求值顺序从左到右

    Order of evaluation

    订购
    ......

    如果子表达式 E1 和 E2 之间存在序列点,则 E1 的值计算和副作用都将在 E2 的每个值计算和副作用之前进行排序

    规则
    .....
    2) 在计算以下二元运算符的第一个(左)操作数之后和第二个(右)操作数之前有一个序列点:&&(逻辑与)、|| (逻辑或)和 ,(逗号)。

    在这个表达式中:

    x = ( y = 3, ( z = ++y + 2 ) + 5 )
    

    首先评估y = 3,然后评估( z = ++y + 2 ) + 5

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-24
      • 2017-06-02
      • 1970-01-01
      相关资源
      最近更新 更多