2014-08-29 65 views
2

我有一些代碼最近被移植到VS.接下來是聲明和彙編器生成的,希望'錯誤'是顯而易見的。當然,它生成這個代碼的方式可能是VS的一個特性,但我不能說我以前見過這個。在VS2013中的一個語句中多指針增量的解決方法

switchcount = (int) (*d++) + (*d++<<8) + (*d++<<16) + (*d++<<24);

00A722F6 mov   eax,dword ptr [d] 
00A722F9 movzx  ecx,byte ptr [eax] 
00A722FC mov   edx,dword ptr [d] 
00A722FF movzx  eax,byte ptr [edx] 
00A72302 shl   eax,8 
00A72305 add   ecx,eax 
00A72307 mov   edx,dword ptr [d] 
00A7230A movzx  eax,byte ptr [edx] 
00A7230D shl   eax,10h 
00A72310 add   ecx,eax 
00A72312 mov   edx,dword ptr [d] 
00A72315 movzx  eax,byte ptr [edx] 
00A72318 shl   eax,18h 
00A7231B add   ecx,eax 
00A7231D mov   dword ptr ds:[0AD8CA8h],ecx 
00A72323 mov   ecx,dword ptr [d] 
00A72326 add   ecx,1 
00A72329 mov   dword ptr [d],ecx 

所以編譯器產生的代碼基本上

switchcount = (int) (*d) + (*d<<8) + (*d<<16) + (*d<<24); 
d += 4 ; 

誰能告訴我如何說服編譯器生成正確的代碼?

回答

3

C不允許在順序點之間多次修改相同的變量,編譯器可以自由地以任何方式處理它 - 生成它所做的代碼就C標準而言完全沒問題,但是更多有用的行爲將中止編譯,或者至少發出一個警告像鏗鏘的作用:

warning: multiple unsequenced modifications to 'd' [-Wunsequenced] 

寫的代碼正確的方法是

switchcount = (int) (d[0]) + (d[1]<<8) + (d[2]<<16) + (d[3]<<24); 
d += 4; 

作爲一個側面說明,投給int是不必要的,因爲使用整數提升,但是如果您希望代碼被C新手讀取,您可以將其保留爲清晰。

根據爲d輸入值,你應該與強制轉換爲unsigned更換投地int - 否則,如果d[3]至少是128,你的最後期限將價值位移位至符號位,這是再次'未定義的行爲'(但通常按預期工作,如果整數由二進制補碼錶示)。

+0

非常感謝您提供清晰簡潔的答案。 很遺憾,這些語言的設計師在工作時並不記得小學BODMAS/BOMDAS。方括號應確保增量在左括號上從左到右發生。 – mvandere 2014-08-29 21:38:40

0

C語言中用於處理像d ++多重時間之類的子表達式的行爲是未定義的。您現在正面臨不同編譯器對不同編譯器的解釋方式 - 避免以這種方式使用表達式。

請參閱Pre & post increment operator behavior in C, C++, Java, & C#

+0

同樣,雖然這個例子對於大多數編譯器是正確的,但簡單的()不會改變它的行爲。 – mvandere 2014-08-29 21:42:48