c++ - 序列点和运算符优先级有什么区别?

标签 c++ c language-lawyer

考虑经典的序列点示例:

i = i++;

C 和 C++ 标准规定上述表达式的行为是未定义的,因为 = 运算符与序列点无关。

让我困惑的是 ++ 的优先级高于 = 因此,上面的表达式,基于优先级,必须计算 i++ 先做作业。因此,如果我们从 i = 0 开始,我们应该总是以 i = 0 结束(或者 i = 1,如果表达式是i =++i) 而不是未定义的行为。我错过了什么?

最佳答案

所有运算符都会产生一个结果。此外,还有一些运算符,如赋值运算符=和复合赋值运算符(+=++>>= 等)产生副作用。结果和副作用之间的区别是这个问题的核心。

运算符优先级控制运算符用于生成结果的顺序。例如,优先规则要求 *+ 之前,+& 之前,依此类推。

但是,运算符优先级并没有说明应用副作用。这就是序列点(之前排序、之后排序等)发挥作用的地方。他们说,为了明确定义表达式,将副作用应用到内存中的同一位置必须用序列点分隔。

i = i++ 打破了这条规则,因为 ++= 都将它们的副作用应用于同一个变量 。首先, ++ 去,因为它有更高的优先级。它通过在增量之前获取 i 的原始值来计算其值。然后 = 去,因为它的优先级较低。它的结果也是i的原始值。

这里缺少的关键是分隔两个运算符的副作用的序列点。这就是行为未定义的原因。

关于c++ - 序列点和运算符优先级有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44770170/

相关文章:

c - 在 C 中使用 mpi 和 lapack 时出现段错误

c++ - 名称查找 "in the class of the object expression"是否应该找到该类的成员?

c++ - 附加到字符串不会更改字符串值

c++ - 一台服务器向一个客户端发送数据。使用 select() 实现非阻塞 I/O

MS-DOS 的 C 编译器

c - ANSI C 的位操作库

c++ - 依赖模板名称和 C++20 ADL

c++ - SFINAE 可以检测到私有(private)访问违规吗?

c++ - 有没有更好的方法来设计这个消息传递代码?

c++ - 基于类型名称的 SFINAE