在同一语句中使用几个递增/递减

时间:2014-03-04 11:13:04

标签: c standards increment undefined-behavior operator-precedence

我知道C中的计算顺序并不严格,因此表达式--a + ++a的值未定义,因为未知哪个语句部分首先运行。

但是,如果我知道计算顺序在特定情况下无关紧要怎么办?例如:

  1. 所有修改都对应于不同的变量(例如a[p1++] = b[p2++]
  2. 顺序无关紧要,就像在a++ + ++a中一样 - 无论+的哪一侧先计算,结果都是两个。是否保证在运行另一个部件之前将完全计算一个部件?即编译器无法记住a++的结果,++a的结果,然后首先应用a++,而不是两个?例如,缓存a的初始值并将其作为参数单独传递给两个运算符。
  3. 我对C,C99,C11,C ++ 03和C ++ 11的答案感兴趣,如果它们之间有任何差异。

2 个答案:

答案 0 :(得分:3)

标准说:

  

在上一个和下一个序列点之间有一个对象   它的存储值最多只能通过评估一次修改   表达。此外,只能访问先前值   确定要存储的值。 / 26 /

     

除非语法/ 27 /或稍后指定   (对于函数调用运算符(),&&,||,?:和逗号   运算符),子表达式的评估顺序和顺序   发生哪些副作用都是未指明的。

所以:

1。)a[p1++] = b[p2++]:保证正确评估语句并给出预期结果。这是因为每个变量只修改一次,结果不依赖于两个变量的实际增量完成的时间。

2。)a++ + ++a:无法保证在第二次使用a之前执行副作用(增量)。因此,此表达式可以赋予值a + (a+1)(a+1) + (a+1)a + (a+2),具体取决于编译器何时执行原始变量的副作用增量。

答案 1 :(得分:0)

Online C 2011 standard

6.5表达
...
3运算符和操作数的分组由语法表示。 85)除非另有规定 之后,子表达式的副作用和值计算没有排序 86)

85)语法规定了运算符在表达式求值中的优先级,这是相同的 作为本条款主要子条款的顺序,首先是最高优先级。因此,例如, 表达式允许作为二进制+运算符(6.5.6)的操作数是那些定义的表达式 6.5.1至6.5.6。例外情况是强制转换表达式(6.5.4)作为一元运算符的操作数 (6.5.3),以及以下任何一对运算符之间包含的操作数:分组 括号()(6.5.1),下标括号[](6.5.2.1),函数调用括号()(6.5.2.2),以及 条件运算符? :(6.5.15)。 在每个主要子条款中,运算符具有相同的优先级。左或右相关性是 在每个子条款中通过其中讨论的表达式的语法表示。

86)在程序执行期间被多次评估的表达式中,未经过排序和 对其子表达式的不确定顺序评估不需要一致地执行 不同的评估。

重点补充。

无法保证在评估其他表达式之前应用a++++a副作用,因此您可以根据顺序获得不同的结果操作。

以下是几种情况,假设a从1开始:

  • 从左到右评价,立即应用副作用:(1)+(2 + 1)== 4
  • 从左到右评价,延迟的副作用:(1)+(1 + 1)== 3
  • 从右到左评估,立即应用副作用:(2)+(1 + 1)== 4
  • 从右到左评估,延迟的副作用:(1)+(1 + 1)== 3

或任何其他组合。