gre*_*emo 1 c variable-assignment operator-precedence undefined-behavior
当l值的评估先于 r 值的评估并且赋值也返回一个值时,首先评估以下哪个值?
int i = 2;
int x[] = {1, 2, 3};
int y[] = {4, 5, 6};
int z[] = {7, 8, 9};
x[--i] = y[++i] = z[i++]; // Out of bound exception or not?
Run Code Online (Sandbox Code Playgroud)
注意:具有l值评估的通用C语言首先出现.从我的教科书:
在一些语言中,例如C,赋值被认为是运算符,其除了产生副作用之外还评估如此计算的r值.因此,如果我们用C写:
x = 2;
Run Code Online (Sandbox Code Playgroud)
除了将值2分配给x之外,对这样一个命令的评估返回值2.因此,在C中,我们还可以写:
y = x = 2;
Run Code Online (Sandbox Code Playgroud)
应解释为:
(y = (x = 2));
Run Code Online (Sandbox Code Playgroud)
我非常确定在这种情况下的行为是未定义的,因为您正在i连续序列点之间多次修改和读取变量的值.
另外,在C中,通过放置[]变量名之后而不是在类型之后声明数组:
int x[] = {1, 2, 3};
Run Code Online (Sandbox Code Playgroud)
从示例中删除数组,因为它们[大部分]无关紧要.现在考虑以下代码:
int main(void)
{
int i = 2;
int x = --i + ++i + i++;
return x;
}
Run Code Online (Sandbox Code Playgroud)
此代码演示了对i原始代码中的变量执行但没有数组的操作.您可以更清楚地看到变量i在此语句中被多次修改.当您依赖于在连续序列点之间修改的变量的状态时,行为是未定义的.不同的编译器(并且GCC返回6,Clang返回5)会给出不同的结果,并且相同的编译器可以使用不同的优化选项给出不同的结果,或者根本没有明显的原因.
如果此语句没有定义的行为,因为i在连续的序列点之间多次修改,那么对于原始代码也可以这样说.赋值运算符不会引入新的序列点.