2013-12-09 69 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的确切用词 - 我很难找到它。 –

相关问题