表达式中的括号是否先评估?

Dur*_*ngh 0 c operator-precedence associativity

在C中,操作数的评估顺序与运算符优先级和关联性无关.

假设我在C中有一个表达式expr1 * expr2 + (expr3 + expr4) (中间没有序列点).

当评估此表达式时,则:

  1. 由于括号,是否会在expr1和expr2之前计算子表达式expr3和expr4?

  2. 或者括号是否确保括号内的运算符在括号外的运算符之前进行求值?

括号是否确保操作数或运算符的评估顺序?

Joh*_*ode 5

从2011年语言标准的在线草案:

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)在程序执行期间不止一次评估的表达式中,不需要在不同的评估中一致地执行其子表达式的未序列和不确定顺序的评估.

清楚如泥,对吗?这意味着,给出一个像这样的表达式

x = a++ + b++ * (--c / ++d)
Run Code Online (Sandbox Code Playgroud)

每个子表达式a++,b++,--c,和++d可被评估以任何顺序 ; 仅仅因为--c并且++d被parens分组并不意味着它们首先被评估.此外,在评估表达后++,--不必立即应用各自的副作用.

所有运算符优先级的保证的是,结果的--c / ++d将通过的结果相乘b++,并且结果a++将被添加到该值; 它不保证任何表达式在任何其他表达式之前得到评估.

脚注86; 如果上面的表达式出现在循环中,则没有理由期望每次循环都会以相同的顺序评估子表达式.实际上,它们很可能是,但编译器明确地给予了动摇的自由.

由于可以自由地评估表达式并以任何顺序应用副作用,因此某些表达式a++ + a++不会产生一致的结果; 标准显式地将其视为未定义的行为,这意味着编译器没有义务以任何特定方式处理该情况.它可以忽略这个问题,它可以发出警告,它可以通过错误等停止转换,但不要求它做任何特定的事情.