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

x = x = 5;

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

我说主要是因为我实际遇到的(用更大的表达)是
x[0][0] = x[0][0] = 5;

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

最佳答案

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

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

一个更令人兴奋的例子是 x[0][0] = x[0][i] = 5; ,当(且仅当) i == 0 时,它​​将分配给同一个对象而没有中间序列点,因此定义的行为取决于 i 的值。

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

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

关于c++ - 未定义的行为或误报,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4129239/

10-12 03:59