【问题标题】:Is this well defined code?这是定义明确的代码吗?
【发布时间】:2011-08-26 18:43:32
【问题描述】:

阅读this主题后,我仍然有些困惑。以下 C++ 表达式 *d++ = ~(*d); 是否定义明确?是的,我知道这样的复合表达式很难看。。不是我写的。

当我将它与生成的程序集进行比较时,我发现它略有不同:

*d = ~(*d);
d++;

组装:

*d++ = ~(*d);
0x83384    LDR           R3,[R0 <d>,4]        <<diff
0x83388    ADD           R1 <c>, R1 <c>, 1
0x8338c    MVN           R3, R3
0x83390    STR           R3,[R0 <d>],4

*d = ~(*d);
d++;
0x83384   LDR           R3,[R0 <d>]
0x83388   ADD           R1 <c>, R1 <c>, 1
0x8338c   MVN           R3, R3
0x83390   STR           R3,[R0 <d>],4

谢谢!

【问题讨论】:

  • 所有汇编器都会告诉你这个特定编译器的这个特定版本对你在这个特定时间使用的设置做了什么。它没有说明标准保证或不保证的内容。
  • 谢谢。我最初认为在这个问题的上下文中查看编译器生成的内容可能会有所帮助。我现在看到可能会生成任何东西(在未定义的情况下)。

标签: c++ operator-precedence


【解决方案1】:

您的表达式具有 undefined(相对于 unspecified)行为。汇编代码也可以演奏贝多芬 9th 并且仍然符合标准。

从神圣的标准,第 5 章,第 4 节:

在前一个和下一个序列点之间,一个标量对象的存储值最多只能通过表达式的计算修改一次。

因此,代码格式不正确。我不知道是否需要一个符合标准的编译器来发出诊断,但我已经被这个问题困扰了足够多的时间,我准备打赌它不是。

更多详情请参考@Prasoon Saurav 的精彩论述there

【讨论】:

  • 太棒了! :)
  • @coward downvoter:请澄清您的意图。我很确定它是 UB 根据 OP 指向的链接,但我可能是错的。
  • 我更喜欢瓦格纳 - 女武神骑!
  • 你能更准确地解释一下它是如何 UB 的吗?是不是因为d 或者d+1 可以用在作业的右边?
  • @BoPersson:这不是原因。 d 递增,d 指向的东西被赋值,这是两个不同的对象。问题是d 的增量和d 在表达式右轴上的读取之间没有序列点,这是一个读取,不能确定增量中写入d 的值操作。
【解决方案2】:
*d++ = ~(*d);

在这个表达式中,没有一个对象会多次存储新值。 d + 1 的值作为增量运算符 (d++) 的副作用存储到 d,并且在赋值运算符写入此增量之前,d 指向的对象的值。

问题在于读取d,不仅是为了确定要写回它的值(即d + 1),而且还读取以确定要从右侧子表达式中读取的地址~(*d).

这违反了 ISO/IEC 14882:2003 5 [expr] / 4 的第三句(为简洁起见,第一句省略):

[...] 在前一个和下一个序列点之间,一个标量对象的存储值最多只能通过表达式的评估修改一次。 此外,只能访问先验值以确定要存储的值。 对于完整表达式的子表达式的每个允许排序,应满足本段的要求;否则行为未定义。

【讨论】:

  • 这是一个非常有用的解释。谢谢。
【解决方案3】:

您只是不知道 ++ 何时被评估。我想您的编译器会在 ~(*d) 之前对其进行评估,这会导致

*d = ~(*(d+1));

因此你的差异。

【讨论】:

  • 什么都别想。没有什么可假设的,根据 C++ ISO 标准,代码格式不正确。
  • 如果您指的是 ++ 在 rhs 查找之前生效,我认为您的意思是 *d=~(*(d+1))。
  • @Alexander C.,我认为 Christian 是在说反汇编示例表明某些特定的编译器首先进行了增量,这与相反顺序的汇编(或期望)不同。跨度>
  • @Alexandre 这正是我的观点。您只是不知道编译器首先评估什么。我只是想给他一个解释,为什么结果与他的假设不同。
  • @Jose_X 是的,你是对的,首先是 ++,然后是 *。我会编辑它。
猜你喜欢
  • 2011-06-10
  • 1970-01-01
  • 2012-09-28
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-25
  • 1970-01-01
相关资源
最近更新 更多