CppCheck警告:表达式依赖于x = x | =(1 << 3)的评估顺序

4

C语言中的代码行为:

x = x |= (1 << 3);

这个代码出现了一个CPPCheck错误:"表达式“x=x|=1”的求值顺序依赖于副作用的顺序"。

而下面这一行:

x |= (1 << 3);

is ok.

I thought

x = x |= (1 << 3);

应该与

x = x = x | (1 << 3);

这只是

x = (x = (x | (1 << 3)));

实际上,对 x 的外部赋值没有任何影响,这意味着结果与

x |= (1 << 3);

那么CppCheck在这里到底在抱怨什么?

编辑:我认为这是与上面提到的问题讨论的j = j++是否与j++相同的重复问题。


1
你可能想要了解一下“序列点(sequence points)”的相关知识。在单个序列点内对变量进行两次修改是未定义的行为。 - Cornstalks
3
可能是为什么使用++运算符的这些语句是未定义行为?的重复。 - too honest for this site
1个回答

4

这个引用来自于 @Cornstalks 的关于序列点的链接,解释得非常好。

表达式……对同一个值进行两次修改是应该被禁止的(或者说,在任何情况下,不需要定义明确,即我们不必强制规定它们的行为,编译器也不必支持它们)。

C标准根本没有规定这些类型的表达式的任何事情,因此在所有环境中都不能保证有特定的评估顺序。

一个非常简单快速的解释:

x = x |= 1在副作用(修改x的值)方面与x = x += 1几乎等价。 在C中,x = x += 1等同于x = ++x。这个表达式是众所周知的未定义的表达式

这里阅读更多信息。


1
根据C标准,“更新左操作数存储值的副作用在左右操作数的值计算之后排序。”并且“3 如果要存储在对象中的值是从与第一个对象以任何方式重叠的另一个对象中读取的,则重叠必须是精确的,并且两个对象必须具有兼容类型的限定或不限定版本;否则,行为未定义。”因此,此表达式是明确定义的。 - Vlad from Moscow
1
@Vlad 是的,副作用在计算之后被排序。然而,C标准还规定:“在前一个和下一个序列点之间,标量对象通过表达式的求值最多只能修改其存储值一次。” 在这个表达式中,x两个 副作用。我认为你的第二个引用与此无关。 - cozyconemotel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接