我(基本上)在野外遇到以下内容
x = x = 5;
显然在早期版本的gcc下干净利落地编译(在gcc 4.5.1下生成警告)。据我所知,警告是由-Wsequence-point生成的。所以我的问题是这是否违反了关于在序列点之间操纵变量的标准中的措辞(即,它是根据规范的未定义行为)或者这是gcc误报(即,它是根据规范定义的行为)?关于序列点的措辞有点难以理解。
我说的基本上是因为我实际遇到的(在一个更大的表达中)是
x[0][0] = x[0][0] = 5;
但是我认为这不是警告的重要信息(请纠正我,如果这是重点,而不是我认为是问题的关键)。
答案 0 :(得分:5)
假设x
是内置类型,它会在没有插入序列点的情况下分配给x
两次,这是您需要知道的全部内容。事实上两个赋值具有相同的值(5),并且理论上可以优化为单个赋值(如果x
不易变),既不在这里也不在那里。
至少,这就是我如何解释标准中的“修改” - 分配了一个值,无论它是否恰好与旧值相同。同样,抛出const并分配给const对象,我认为是UB,无论你指定的值是否恰好等于先前值。否则,如果一个实现想要将字符串文字放入ROM中,以防止页面错误,那么所有内存写入都会产生巨大的开销,并且我们通过检查知道编译器不会发出该代码。
一个更令人兴奋的例子是x[0][0] = x[0][i] = 5;
,如果(并且仅当)i == 0
,它将分配给同一个对象而没有插入序列点,所以定义的行为是以{{i
的值为条件的。 1}}。
我不明白为什么编译器可能会在任何一种情况下做任何意想不到的事情,但同样我缺乏想象力是无关紧要的: - )
能干的说法是对的。如果您在某些不能使用两个语句的环境中,可以写一下x[0][0] = 5, x[0][i] = 5
。在您的两种情况下,只需抛弃冗余分配。