表达式x [ - i] = y [++ i] = z [i ++],首先进行评估?

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)

dre*_*lax 6

我非常确定在这种情况下的行为是未定义的,因为您正在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在连续的序列点之间多次修改,那么对于原始代码也可以这样说.赋值运算符不会引入新的序列点.

  • @Gremo:然后你必须用你的伪语言标准来查找它. (10认同)