当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?
注意:通用的C语言,首先是l值评估。 从我的教科书:
在某些语言中,例如C, 任务被认为是一种 另外,运营商的评估 也产生副作用 返回如此计算的r值。 因此,如果我们用C编写:
x = 2;
评估这样一个命令 除了将值2赋值给x之外, 返回值2.因此,在C中, 我们也可以写:
y = x = 2;
应解释为:
(y = (x = 2));
答案 0 :(得分:6)
我非常确定这种情况下的行为是未定义的,因为您在连续序列点之间多次修改和读取变量i
的值。
此外,在C中,通过将[]
放在变量名之后而不是在类型之后声明数组:
int x[] = {1, 2, 3};
从示例中删除数组,因为它们[大部分]无关紧要。现在考虑以下代码:
int main(void)
{
int i = 2;
int x = --i + ++i + i++;
return x;
}
此代码演示了对原始代码中的变量i
执行但没有数组的操作。您可以更清楚地看到变量i
在此语句中被多次修改。当您依赖于在连续序列点之间修改的变量的状态时,行为是未定义的。不同的编译器(并且GCC返回6,Clang返回5)会给出不同的结果,并且相同的编译器可以使用不同的优化选项给出不同的结果,或者根本没有明显的原因。
如果此语句没有定义的行为,因为i
在连续序列点之间被多次修改,那么对于原始代码也可以这样说。赋值运算符不会引入新的序列点。
答案 1 :(得分:2)
在C中,两个sequence points之间的任何操作的顺序都不应该依赖于。我不记得标准中的确切措辞,但出于这个原因
i = i++;
是未定义的行为。该标准定义了组成sequence points
的事物列表,从内存中可以看出
在维基百科上查找页面,列表更完整,更详细地描述。序列点是C中非常重要的概念,如果您还不知道它的含义,请立即学习。
无论评估和分配x
,y
和z
变量的顺序如何明确,
x[--i] = y[++i] = z[i++];
由于i--
,i++
和i++
,此语句不能是未定义的行为。
另一方面
x[i] = y[i] = z[i];
定义明确,但我不确定此评估顺序的状态。如果这很重要,我宁愿把它分成两个语句,同时注释“重要的是......在...之前分配/初始化......因为......”。
答案 2 :(得分:-3)
我认为它与
相同x[3] = y[4] = z[2];
i = 3;