2016-11-07 83 views
5

奇怪的行爲,我對計算機科學的教學助理和我的一個學生提出以下的代碼來檢查一個整數是否是奇數還是偶數:檢查一個數字是否在C++中是奇數。代碼

int is_odd (int i) { 
    if((i % 2 == 1) && (i % 2 == -1)); 
    else; 
} 

令人驚訝的(至少對我來說)這個代碼提供正確的結果。我測試了高達100000000的數字,並且我實在無法解釋爲什麼這個代碼的行爲與它一樣。

我們正在使用gcc V6.2.1和C++

我知道,這是不是這麼一個典型的問題,但我希望能找到一些幫助。

+6

給出正確結果?該函數應該返回一個int,但不返回任何內容。它的行爲是不確定的。你如何確定結果是「正確的」? – StoryTeller

+0

當你實際修復它時,它根本不正確。 http://ideone.com/5bs2aF – StoryTeller

+0

行爲未定義。看看[這裏](http://melpon.org/wandbox/permlink/HbRsBuRh5fAnBA0U)。我們可以構建一個關於'mod'的論據或者在'eax'中相應地留下'0'或'1'的東西,但是它很脆弱 – krzaq

回答

15

不考慮實際發生在您的編譯器中的情況,在不返回任何東西的情況下流動函數的末尾是未定義的行爲。請注意,如果您通過-O3GCC或使用Clang,那麼您會得到不同的結果。

至於爲什麼你實際看到的「正確」的答案,這是x86組件,GCC 6.2會產生在-O0

push rbp 
    mov  rbp, rsp 
    mov  DWORD PTR [rbp-4], edi 
    mov  eax, DWORD PTR [rbp-4] 
    cdq 
    shr  edx, 31 
    add  eax, edx 
    and  eax, 1 
    sub  eax, edx 
    cmp  eax, 1 
    nop 
    pop  rbp 
    ret 

,如果你不能閱讀的x86別擔心。重要的是要注意的是,eax用於返回值,並且if語句的所有中間計算都使用eax作爲其目標。所以當函數退出時,eax恰好有分支檢查的結果。

當然,這純屬學術討論;學生的代碼是錯誤的,我肯定會給它零分,不管它是否通過了你運行的任何測試。

+2

我認爲,通過改變調用約定可以進一步證明這一點的脆弱性。 – StoryTeller

+1

是的代碼可能是錯誤的,但我仍然想知道爲什麼它仍然有效,因爲我想了解爲什麼系統的行爲像它一樣。 (因爲每一個好的計算機科學家都應該這樣做)) – DonMushroom

+0

downvote的任何原因?也許我試圖解釋一些UB會激怒某人:D – TartanLlama

相關問題