2013-12-09 107 views
3

考慮一塊的C++代碼:爲什麼會產生這樣奇怪的代碼?

int main() 
{ 
    volatile int a=0; 
    if(!a) 
     ++a; 
} 

予編譯它AMD64系統上 克++(Ubuntu的4.8.1-2ubuntu1〜12.04)與命令g++ test.cpp -S -o test.S -masm=intel並獲得以下代碼:

... 
    mov eax, DWORD PTR [ebp-4] 
    test eax, eax 
    sete al 
    test al, al 
    je .L2 
    mov eax, DWORD PTR [ebp-4] ; don't use result of sete 
    add eax, 1 
    mov DWORD PTR [ebp-4], eax 
.L2: 
    mov eax, 0 ; also drop result of sete 
... 

這段代碼真的讓我感到驚訝。起初我認爲它與64位模式有關。但是當我試圖編譯-m32時,這一點保持不變。

爲什麼它檢查eax爲零,然後在將al設置爲ZF後再次檢查結果?爲什麼它不只是test eax,eax\n jne .L2

+1

打開優化(命令行上的-O3),無用的指令將消失。 –

+0

@NilsPipenbrinck我知道優化。問題是關於爲什麼如此,而不是如何解決。 – Ruslan

回答

6

我認爲這與bool在C和C++中的處理方式有關。在您的代碼中,if(!a)首先將a轉換爲bool(這就是test eax, eax; sete al所做的),然後然後測試布爾值(在al中)是否爲true/false。

如果您重命名爲.cgcc編譯相同的代碼,它產生預期的代碼

mov DWORD PTR [rbp-4], 0 
    mov eax, DWORD PTR [rbp-4] 
    test eax, eax 
    jne .L3 
    mov eax, DWORD PTR [rbp-4] 
    add eax, 1 
    mov DWORD PTR [rbp-4], eax 
.L3: 

在C,似乎整體變量的布爾測試情況沒有中間轉換bool。請注意,al從不涉及,所以這意味着該值在測試爲非零之前從未「轉換」爲單字節bool

+0

這很有道理,謝謝。 – Ruslan

+0

也許其中一位C/C++語言大師可以在這裏指出spec的確切用詞 - 我很難找到它。 –

相關問題