2011-12-23 41 views
4

輸入K & R 1 -CH 1:++ NC VS NC = NC + 1

聲明++nc提出了一種新運營商,++,其通過一個裝置增量。你可以改爲寫nc = nc + 1,但++nc更簡潔,通常效率更高。

什麼時候預增加比替代方案更有效率?對於大多數情況來說,至少對於兩者來說,彙編都是add(編輯:或inc)指令。它們何時有所不同?

+0

我知道這是標記爲C,並糾正我,如果我錯了,但作爲一個好奇心,我相信後增量可能會慢於C++前增量,即使在現代編譯器。因爲C++標準強制執行後增量來調用對象的複製構造函數。參考,[C++ FAQ](http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.15)。 – Lundin 2011-12-23 10:07:36

回答

10

該文本長期過期。在70年代,編譯器可能會爲++ n生成更高效的輸出,但現在不再是這樣。所有現代編譯器都會生成相同的代碼。

+0

澄清 - 當C編譯器愚蠢且沒有優化時,'++'操作符最初被添加到C中,所以'x = x + 1','x + = 1'和'x ++'都可能被編譯爲不同的彙編代碼。當然,現在編譯器比這更聰明。 – 2011-12-23 09:04:24

+0

我想我太年輕了。謝謝您的幫助。 – mwlow 2011-12-23 09:11:11

+0

啊,現在你讓我感覺老了! - ;) – 2011-12-23 09:16:31

3

對於大多數情況來說,至少對於兩者來說,程序集都是add指令。

這不是真的:經常有separate "increment by one" instruction。但是,這是無關緊要的,因爲任何半面編譯器都會爲++ncnc = nc + 1生成相同的機器碼。

換句話說,沒有性能差異。這本書的寫作和編譯器可能不是很好,但現在已經不存在了。

2

我不肯定知道,我只是想出來大聲(也許我不應該):或許以K &的r時間,++nc被編譯成東西比nc = nc + 1更有效(例如,增量指令,而不是增加)。但是,現在編譯器可能會自動優化。

+0

我相信'++'已經被加到C早期了,因爲沒有人編寫過足夠複雜的編譯器來自動使用遞增指令。 – 2011-12-23 09:05:40

+0

當時有足夠好的編譯器可用,而不是K&R在編寫第一個C編譯器時使用的24 kB機器。這是一個*迷你電腦*裝在一個房間裏。 :-) http://cm.bell-labs.com/cm/cs/who/dmr/ken-and-den.jpg – 2011-12-23 11:56:34

1

這是我所能看到的gcc -S <filename>。我會讓你得到你想要的!

> 
> cat 1.c 
    #include <stdio.h> 

    int main() 
    { 
     int i=0; 
     ++i; 

     return 0; 
    } 

> 
> cat 2.c 
#include <stdio.h> 

int main() 
{ 
    int i=0; 
    i++; 

    return 0; 
} 

> 
> cat 3.c 
#include <stdio.h> 

int main(void) 
{ 
    int i=0; 
    i = i + 1; 

    return 0; 
} 
> 
> gcc -S 1.c 2.c 3.c 
> 
> 
> diff 1.s 2.s 
1c1 
<  .file "1.c" 
--- 
>  .file "2.c" 
> 
> diff 2.s 3.s 
1c1 
<  .file "2.c" 
--- 
>  .file "3.c" 
> 
> diff 3.s 1.s 
1c1 
<  .file "3.c" 
--- 
>  .file "1.c" 
> 
> 

下面是.s文件爲1.c的內容和時2.S和3.S比較指令是相同的!

> cat 1.s 
     .file "1.c" 
     .text 
.globl main 
     .type main, @function 
main: 
.LFB2: 
     pushq %rbp 
.LCFI0: 
     movq %rsp, %rbp 
.LCFI1: 
     movl $0, -4(%rbp) 
     addl $1, -4(%rbp) 
     movl $0, %eax 
     leave 
     ret 
.LFE2: 
     .size main, .-main 
     .section  .eh_frame,"a",@progbits 
.Lframe1: 
     .long .LECIE1-.LSCIE1 
.LSCIE1: 
     .long 0x0 
     .byte 0x1 
     .string "zR" 
     .uleb128 0x1 
     .sleb128 -8 
     .byte 0x10 
     .uleb128 0x1 
     .byte 0x3 
     .byte 0xc 
     .uleb128 0x7 
     .uleb128 0x8 
     .byte 0x90 
     .uleb128 0x1 
     .align 8 
.LECIE1: 
.LSFDE1: 
     .long .LEFDE1-.LASFDE1 
.LASFDE1: 
     .long .LASFDE1-.Lframe1 
     .long .LFB2 
     .long .LFE2-.LFB2 
     .uleb128 0x0 
     .byte 0x4 
     .long .LCFI0-.LFB2 
     .byte 0xe 
     .uleb128 0x10 
     .byte 0x86 
     .uleb128 0x2 
     .byte 0x4 
     .long .LCFI1-.LCFI0 
     .byte 0xd 
     .uleb128 0x6 
     .align 8 
.LEFDE1: 
     .ident "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-48)" 
     .section  .note.GNU-stack,"",@progbits 
> 
1

對於「正常」變量,應該沒有區別,因爲其他答案的建議。只有nc是​​合格,結果可能會有所不同。對於這樣的變量,+1形式必須首先評估表達式nc,即加載nc,然後執行加法。對於++表單,編譯器仍然可以採取快捷方式並且適當增加變量。

相關問題