[英]Why v[i] = i++ is undefined behavior in C?
阅读有关ACCU过载的有趣文章#115:“恶魔可能会飞出你的鼻子”我发现作者说:
在序列点之间,不允许对涉及变量的状态做出任何假设。 这也意味着在C中,与大多数其他语言不同,以下表达式会导致未定义的行为
v [i] = i ++;
因为赋值运算符不代表C中的序列点
有人可以解释一下UB的详细推理是什么吗? 我认为在两个序列点之间对同一个变量进行多次写操作是个问题,除了v [i]别名的可能性之外我在这里看不到...
这不仅仅是写作。 当您不知道是否正在读取变量的旧值或新值时,读取也会发挥作用。 在这种情况下,有没有办法说是否v[i]
指的是旧值i
,或者新的价值i
。
例如,表达式v[i] = i++
可以解释为
v[i] = i
i
或者,它可以解释为
i
的旧值: i_old = i
i
v[i] = i_old
您可以很容易地看到,代码的行为会根据其解释方式而改变。 这些只是两种可能的不一致情况的例子。
但该语言并未将行为限制在如此有限的各种场景中。 相反,语言表示行为是未定义的,这意味着,除其他外,编译器可以自由地拒绝以任何“可预测”的方式解释此代码。
在同一序列点内有i
的读和写。 也就是说,在计算v[i]
的地址之后, i++
可以在OR之前改变i。 实际上,因为这种行为是未定义的,所以它们很可能都不会做这些事情 - 例如,编译器可以假定语句不可访问并将其删除。 (或让恶魔飞出你的鼻子等)
你是正确的,在没有插入序列点的情况下多次修改变量会导致不确定的行为。 但是还有一个额外的要求,即仅访问变量的值以确定要修改的值。 这是不允许的第二个要求
v[i] = i++;
这里对数组索引的i
值的访问与对i
( i++
)的修改无关。 由于两次访问之间没有中间序列点,因此这是未定义的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.