2011-05-16 70 views
10

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

谢谢!

+0

所有汇编是要告诉你的是什么这个特殊的编译器的这个特定版本与您使用这个特定时刻的设置一样。它没有说什么是标准保证或不保证的。 – 2011-05-16 22:25:09

+0

谢谢。我最初认为在这个问题的背景下看看编译器产生了什么可能会有所帮助。我现在看到任何东西(在未定义的情况下)都可能产生。 – Mav3rick 2011-05-16 22:42:09

回答

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

在这个表达式中,没有任何对象多次存储新的值。 d + 1的值作为增量运算符(d++)的副作用和d指向的对象的值存储到d,然后该赋值运算符将写入该增量。

问题是d被读取时,不只是确定该值被写回它(即d + 1),但也被读取以确定从在右侧子表达式~(*d)读出地址。

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

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

+0

这是一个非常有用的解释。谢谢。 – Mav3rick 2011-05-16 22:19:15

11

你的表达具有未定义(相对于未指定)行为。汇编代码也可以播放贝多芬9号,并且仍然符合标准。

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

之前和下一序列点之间的标量对象应具有其存储的值由表达式的评估修饰的至多一次。

因此,代码格式不正确。我不知道是否符合标准的编译器需要需要才能发布诊断,但我已经被足够多的时间通过这个,我准备好打赌它不是。

有关更多详细信息,请参阅@Prasoon Saurav的优秀博览会there

+0

我希望它能做到。 – Femaref 2011-05-16 21:12:52

+0

* *会是非常可怕的! :) – FrustratedWithFormsDesigner 2011-05-16 21:13:00

+0

@coward downvoter:请澄清你的意图。我很确定这是每个OP指向的链接都是UB,但我可能是错的。 – 2011-05-16 21:15:38

1

你只是不知道++何时被评估。我想你的编译器,导致

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

因此您dicrepancy的~(*d)之前对其进行评估。

+0

不要假设任何东西。没有什么可设想的,代码是根据C++ ISO标准生成的。 – 2011-05-16 21:23:29

+0

我觉得你的意思* d =〜(*(d + 1)),如果你指的是RHS查找前++生效。 – 2011-05-16 21:58:32

+0

@Alexander C.,我认为基督教是说,拆卸例子表明,一些特定的编译器第一次做的增量,这将是比对排序的组件(或预期)不同。 – 2011-05-16 22:02:19