輸入K & R 1 -CH 1:++ NC VS NC = NC + 1
聲明
++nc
提出了一種新運營商,++
,其通過一個裝置增量。你可以改爲寫nc = nc + 1
,但++nc
更簡潔,通常效率更高。
什麼時候預增加比替代方案更有效率?對於大多數情況來說,至少對於兩者來說,彙編都是add
(編輯:或inc
)指令。它們何時有所不同?
輸入K & R 1 -CH 1:++ NC VS NC = NC + 1
聲明
++nc
提出了一種新運營商,++
,其通過一個裝置增量。你可以改爲寫nc = nc + 1
,但++nc
更簡潔,通常效率更高。
什麼時候預增加比替代方案更有效率?對於大多數情況來說,至少對於兩者來說,彙編都是add
(編輯:或inc
)指令。它們何時有所不同?
該文本長期過期。在70年代,編譯器可能會爲++ n生成更高效的輸出,但現在不再是這樣。所有現代編譯器都會生成相同的代碼。
澄清 - 當C編譯器愚蠢且沒有優化時,'++'操作符最初被添加到C中,所以'x = x + 1','x + = 1'和'x ++'都可能被編譯爲不同的彙編代碼。當然,現在編譯器比這更聰明。 – 2011-12-23 09:04:24
我想我太年輕了。謝謝您的幫助。 – mwlow 2011-12-23 09:11:11
啊,現在你讓我感覺老了! - ;) – 2011-12-23 09:16:31
對於大多數情況來說,至少對於兩者來說,程序集都是add指令。
這不是真的:經常有separate "increment by one" instruction。但是,這是無關緊要的,因爲任何半面編譯器都會爲++nc
和nc = nc + 1
生成相同的機器碼。
換句話說,沒有性能差異。這本書的寫作和編譯器可能不是很好,但現在已經不存在了。
我不肯定知道,我只是想出來大聲(也許我不應該):或許以K &的r時間,++nc
被編譯成東西比nc = nc + 1
更有效(例如,增量指令,而不是增加)。但是,現在編譯器可能會自動優化。
我相信'++'已經被加到C早期了,因爲沒有人編寫過足夠複雜的編譯器來自動使用遞增指令。 – 2011-12-23 09:05:40
當時有足夠好的編譯器可用,而不是K&R在編寫第一個C編譯器時使用的24 kB機器。這是一個*迷你電腦*裝在一個房間裏。 :-) http://cm.bell-labs.com/cm/cs/who/dmr/ken-and-den.jpg – 2011-12-23 11:56:34
這是我所能看到的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
>
對於「正常」變量,應該沒有區別,因爲其他答案的建議。只有nc
是合格,結果可能會有所不同。對於這樣的變量,+1
形式必須首先評估表達式nc
,即加載nc
,然後執行加法。對於++
表單,編譯器仍然可以採取快捷方式並且適當增加變量。
我知道這是標記爲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