繁体   English   中英

为什么v [i] = i ++在C中是未定义的行为?

[英]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++可以解释为

  1. 执行赋值: v[i] = i
  2. 增量i

或者,它可以解释为

  1. 得到i的旧值: i_old = i
  2. 增量i
  3. 执行赋值: v[i] = i_old

您可以很容易地看到,代码的行为会根据其解释方式而改变。 这些只是两种可能的不一致情况的例子。

但该语言并未将行为限制在如此有限的各种场景中。 相反,语言表示行为是未定义的,这意味着,除其他外,编译器可以自由地拒绝以任何“可预测”的方式解释此代码。

在同一序列点内有i的读和写。 也就是说,在计算v[i]的地址之后, i++可以在OR之前改变i。 实际上,因为这种行为是未定义的,所以它们很可能都不会做这些事情 - 例如,编译器可以假定语句不可访问并将其删除。 (或让恶魔飞出你的鼻子等)

你是正确的,在没有插入序列点的情况下多次修改变量会导致不确定的行为。 但是还有一个额外的要求,即仅访问变量的值以确定要修改的值。 这是不允许的第二个要求

v[i] = i++;

这里对数组索引的i值的访问与对ii++ )的修改无关。 由于两次访问之间没有中间序列点,因此这是未定义的行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM