2013-12-09 9 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), а затем проверяет, что boolean (in al) для true/false.

Если переименовать в .c и компилировать тот же код с gcc, он генерирует соответствующий код

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++ может указать точную формулировку из спецификации здесь - мне трудно найти его. –

Смежные вопросы