【问题标题】:Undefined behavior or false positive未定义的行为或误报
【发布时间】:2010-11-08 23:56:04
【问题描述】:

我(基本上)在野外遇到过以下情况

x = x = 5;

显然在早期版本的 gcc 下编译干净(在 gcc 4.5.1 下生成警告)。据我所知,警告是由 -Wsequence-point 生成的。所以我的问题是这是否违反了标准中关于在序列点之间操作变量的措辞(即,它是根据规范未定义的行为)还是这是一个 gcc 误报(即,它是根据规范定义的行为)?序列点的措辞有点难以理解。

我之所以这么说主要是因为我实际上遇到的(用更大的表达方式)是

x[0][0] = x[0][0] = 5;

但我不认为这对警告很重要(如果这是重点,而不是我认为是问题的症结,请纠正我)。

【问题讨论】:

  • 无论它是否违反标准中的措辞,它都是糟糕的代码。用火杀死它!让这样的表达式再也不会让你的代码变暗。
  • @abelenk 同意。这不是我的代码,我想在将其提交给 CCB 之前确定它是 UB。

标签: c++ gcc g++ gcc-warning


【解决方案1】:

假设x 是内置类型,它会分配给x 两次而没有中间序列点,这就是您需要知道的全部内容。两个赋值具有相同的值 (5),并且理论上可以优化为单个赋值(如果 x 不是易失性的话)这一事实既不存在也不存在。

至少,这就是我在标准中解释“修改”的方式 - 分配一个值,无论它是否恰好与旧值相同。同样,我认为,抛弃 const 并分配给 const 对象是 UB,无论您分配的值是否恰好等于先前的值。否则,如果一个实现想要将字符串文字放入 ROM 中,以防止在这种情况下出现页面错误,所有内存写入都会产生巨大的开销,并且我们通过检查知道编译器不会发出该代码。

一个更令人兴奋的例子是x[0][0] = x[0][i] = 5;,当(且仅当)i == 0 时,它分配给同一个对象而没有插入序列点,因此定义的行为以i 的值为条件。

我不太明白为什么编译器会在这两种情况下做任何意想不到的事情,但我缺乏想象力再次无关紧要:-)

ablenky 说的是对的。如果您在某些情况下不能使用两个语句,则可以改写x[0][0] = 5, x[0][i] = 5。在您给定的两种情况下,只需放弃冗余分配即可。

【讨论】:

  • 不完全正确:如果 x 恰好是带有 operator= 的用户定义类型,则 x = x = 5 具有与每个成员函数调用关联的序列点,因此会产生定义的行为。
  • @Tony:很公平。这正是我说“假设 x 不是类类型”的原因,但我忘记了它具有联合类型的可能性。
  • 是内置类型的一个很好的答案,只是想讨论类,因为这可能与发帖者是否可以将其标记为他的“CCB”的问题有关。
猜你喜欢
  • 2017-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多