3

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

x = x = 5;

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

我说主要是因为我实际遇到的(用更大的表达方式)是

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

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

4

1 回答 1

5

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

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

一个更令人兴奋的例子是x[0][0] = x[0][i] = 5;,它在没有插入序列点的情况下分配给同一个对象 if (且仅当)i == 0,所以定义的行为取决于 的值i

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

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

于 2010-11-09T00:18:10.553 回答