右侧总是会在左侧前方进行评估吗?然后右侧的结果将传递到左侧。我不是在讨论诸如A[i]=i++
我说的是正常情况:
A[i] = (j+32+43 & K);
A[j] != (A[j] + A[k]);
首先评估所有这些表达式的正确部分,然后将结果与左侧进行比较? (始终)
答案 0 :(得分:5)
不,没有这样的保证,N1570§6.5.16/ p3(强调我的):
赋值运算符将值存储在由指定的对象中 左操作数。赋值表达式的值为left 赋值后的操作数,111)但不是左值。的类型 赋值表达式是左操作数之后的类型 左值转换。更新存储值的副作用 左操作数在左和右的值计算之后排序 正确的操作数。 对操作数的评估未经过排序。
请注意,赋值运算符“使用”两个操作数,并且具有修改左值的副作用。
答案 1 :(得分:4)
一般来说,子表达式的评估顺序是未指定的,有一些例外,例如逻辑和,逻辑或,逗号运算符等...
由于您comment声明您对一般规则感兴趣:
任何操作员@YuHao如果有任何一般规则
draft C99 standard部分6.5
表达式段3
所涵盖的内容(强调我的前进):
运算符和操作数的分组由语法表示.74) 除非后面指定(对于function-call(),&&,||,?:,和 逗号运算符),子表达式的评估顺序和 发生副作用的顺序都是未指明的。
这在draft C11 standard中基本相同,期望C11不列出异常,因此引用C99更方便。 C11中的第3
段说:
运算符和操作数的分组由语法表示.85) 除了后面指定的,副作用和价值计算 子表达式没有排序 .86)
专门针对赋值运算符 C99说:
操作数的评估顺序未指定[...]
和C11说:
[...]对操作数的评估没有考虑。
答案 2 :(得分:1)
我今天刚刚遇到这个,花了1个小时调试这样的代码:
int a[1], b=0;
a[b++] = b;
我希望a [0]在此之后包含0,但编译器实际上决定首先评估b ++,然后是赋值的右侧,并将结果存储在[0]中(因此左侧的b ++工作正常)。所以这实际上变成了:
b++;
a[0] = b; // 1
答案 3 :(得分:0)
这取决于所涉及的运营商的优先级和关联性。
可以找到完整列表here