ze_hit 2022-07-03 10:04 采纳率: 0%
浏览 55

C++中求值顺序和序列点

今天在CSDN上看到一篇有关C++求值顺序和序列点的博客
https://blog.csdn.net/a3192048/article/details/81079262

这是博主从其他论坛转来的,原文地址已经打不开了。看描述应该是一篇陈年老文,但是作者应该是一个有名的博主,该博客也相继被很多博主在多个论坛上转载。虽然“序列点”规则在C++11起已经被“按顺序早于”规则所取代,后者也确实更加完善,但是有一些年代久远一些的工程还在使用C++03标准(毕竟有些公司不愿意花时间精力重构代码),所以我觉得这篇博客还是有一定的参考意义。在仔细研读这篇博客时,有一个问题深深困扰了我,求大家指点迷津,问题如下:

原文第7节描述了C++03中两处关于lvalue的修改对序列点的影响

img

看到这里,瞬间感觉整个人都不好了,就好像突然有人告诉我1+1并不一定等于2,以前的认知被颠覆了!如果真如作者所说,诸如 j = ++i 都是未定义行为,那现有的一大堆C++代码都将是bug的存在啊!

言归正传,经过我的苦思冥想,勉强找到一种说法来解释。原文第3节作者讲了有关序列点的未定义行为

img

仔细阅读作者引用的英文标准,其中 prior value 的意思应该是读取修改之前的先前值吧,而作者下面配的中文解释却好像忽略了先前值这个概念,同样的,cppreference(https://zh.cppreference.com/w/cpp/language/eval_order)中关于序列点的描述中也做了如下规定:

  1. 前后序列点间,至多可以修改在同一个内存位置中的任何对象的存储值一次,否则行为未定义。
  2. 前后序列点间,访问表达式求值所修改的在同一个内存位置中的任何对象的先前值,必须只为确定要存储的值。如果以其他任何方式访问,那么行为未定义。

为保险起见,我又查了C++03标准,ISO/IEC 14882:2003(E)原文如下:

img

由此推断作者对英文标准的解读可能出现了一些偏差?回到原文第7节,作者举的例子,无论是 i = j = 1 ,还是 i= ++j ,似乎都没有违反原文第3节英文标准和cppreference中相邻序列点间的规定吧,而作者在原文第7节提到的“因为标准规定两个相邻序列点之间的读取只能用于决定修改对象的新值,而不能发生在修改之后再读取。”和“同样是因为lvalue作为assignment operator的右操作数需要一个左值转换,该转换导致了一个读取动作且这个读取动作发生在修改对象之后”似乎都和第3节的英文标准的描述的意思不太相符?

当然以上只是我的个人粗浅理解,本人才疏学浅,水平肯定远不如原文作者,原文作者好像在业界地位不低,我也觉得原文作者不应该出错,但是又实实在在感觉匪夷所思。恳请大家指点,告诉我原文作者的观点是不是正确的?谢谢!

  • 写回答

1条回答 默认 最新

  • 真相重于对错 2022-07-03 11:41
    关注

    个人以为这个东西,其实可以上升到哲学问题,也就是什么是真实的?
    中国人学习任何东西都喜欢引经据典,似乎只有经书上的东西才是真理。反驳对方的经常出现就是书上不是这么说的。
    其实这种想法是和现代科学相违背的,现代科学其实就6个字,观测,实践,数学。
    投影到计算机上来说,编译器的实现就是现实,对于某种编译器来说这一次编译的结果,同样的代码下一次依然如此,这就是现实的结果。

    评论

报告相同问题?

问题事件

  • 创建了问题 7月3日

悬赏问题

  • ¥15 在获取boss直聘的聊天的时候只能获取到前40条聊天数据
  • ¥20 关于URL获取的参数,无法执行二选一查询
  • ¥15 液位控制,当液位超过高限时常开触点59闭合,直到液位低于低限时,断开
  • ¥15 marlin编译错误,如何解决?
  • ¥15 有偿四位数,节约算法和扫描算法
  • ¥15 VUE项目怎么运行,系统打不开
  • ¥50 pointpillars等目标检测算法怎么融合注意力机制
  • ¥20 Vs code Mac系统 PHP Debug调试环境配置
  • ¥60 大一项目课,微信小程序
  • ¥15 求视频摘要youtube和ovp数据集