这是定义良好的代码吗?

时间:2011-05-16 21:10:28

标签: c++ operator-precedence

在阅读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

VS

*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

谢谢!

3 个答案:

答案 0 :(得分:11)

您的表达式有 未定义 (与未指定的相反)行为。汇编代码也可以发挥贝多芬的第9名,并且仍然符合标准。

从圣标,第5章,第4节:

  

在上一个和下一个序列点之间,标量对象的表达式评估最多只能修改一次存储值。

因此,代码格式不正确。我不知道符合标准的编译器是否需要来发出诊断信息,但是我已经被咬了很多次,我已经准备好打赌它不是。

有关更多详情,请参阅@Prasoon Saurav的精彩博览会there

答案 1 :(得分:9)

*d++ = ~(*d);

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

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

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

  

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

答案 2 :(得分:1)

你只是不知道什么时候评估++。我想你的编译器会在导致

~(*d)之前对其进行评估
*d = ~(*(d+1));

因此你的双重性。