2017-05-24 250 views
1
u8 num[] = {0x00, 0x00, 0x40}; 

u8*ptr = num; 

u8 tag; 

u16 len; 

tag = *ptr++; 

len = (u16)*ptr++ <<8 | *ptr++; 

我希望len = 0x0040但LEN在Visual Studio 2013年 設置好的與0x0000我不知道這是爲什麼發生。 你會用運算符優先級來解釋嗎?運營商

+2

添加一些括號,您將不需要依賴運算符優先級。問題解決了。 (儘管用++可能會有未定義的行爲) – byxor

+2

答案很簡單:不要編寫那樣的代碼。用圓括號或單獨的行編寫它,然後讓編譯器優化它。 –

+0

[爲什麼這些構造(使用++)未定義的行爲?](https://stackoverflow.com/questions/949433/why-are-these-constructs-using-undefined-behavior) –

回答

1

關於運營商的優先權,我建議你先看看這個table

現在,++/--可能會非常棘手,因爲運營商需要確定他們是否是前綴或後綴運算符,你可以在表中看到,如果他們前綴的人,他們會具有相同的優先級比*(解引用) 。

那麼,讓我們analize做什麼用你的最後一行len = (u16)*ptr++ <<8 | *ptr++;去,有這一套運營商{=, (cast), *(dereference), ++(postfix), <<, |}的,所以根據這個table評價的順序將是++(postfix), *dereference, (type), <<, |, =

這會是關於以評估順序,但你需要考慮:

後綴遞增/遞減具有高優先級,但操作數的 實際增量或減量延遲(以 某個時候完成的語句完成EXECUT前離子)。

這就是說,這裏的一對夫婦的方式來實現你想要什麼:

ptr[1]<<8 | ptr[2] 

或:

*(ptr+1) <<8 | *(ptr+2) 

最後一個建議,要小心,當你處理與運營商正如您在表格中看到的,相同的優先級可以是從左到右或從右到左。

PS:當然,生成將取決於所使用的編譯器&配置的彙編代碼,這裏是在該行的調試模式vs2015的例子:

; 7 :  u16 len = (u16)*ptr++ <<8 | *ptr++; 

    mov ecx, DWORD PTR _ptr$[ebp] 
    movzx edx, BYTE PTR [ecx] 
    shl edx, 8 
    mov eax, DWORD PTR _ptr$[ebp] 
    movzx ecx, BYTE PTR [eax] 
    or edx, ecx 
    mov WORD PTR _len$[ebp], dx 
    mov edx, DWORD PTR _ptr$[ebp] 
    add edx, 1 
    mov DWORD PTR _ptr$[ebp], edx 
    mov eax, DWORD PTR _ptr$[ebp] 
    add eax, 1 
    mov DWORD PTR _ptr$[ebp], eax 

編碼愉快。

+0

'++'的副作用沒有排序,並且操作數可能比您在列表中給出的時間早 –

+0

@MM Op說他正在使用visual studio 2013,我已經測試過並且已經提到了該編譯器,你能詳細說明你的意思嗎? – BPL

+1

不存在您聲明的順序(在標準C++中)。在特定運行的vC++上觀察到的行爲可能會或可能不會在其他運行中被複制,即使使用相同的編譯器 –