在C中,i ++和++ i之間是否存在性能差別?

若是不使用結果值, i++++i之間會有性能差別嗎? 程序員


#1樓

請不要讓「哪一個更快」的問題成爲使用哪一個的決定因素。 您永遠都不會在意那麼多,此外,程序員的閱讀時間比機器學習的時間要昂貴得多。 機器學習

使用對人類閱讀代碼最有意義的方法。 函數


#2樓

我老是喜歡預增量,可是... 性能

我想指出的是,即便在調用operator ++函數的狀況下,若是函數被內聯,編譯器也將可以優化掉臨時函數。 因爲operator ++一般很短,而且常常在標頭中實現,所以極可能會內聯。 學習

所以,出於實際目的,這兩種形式的性能可能沒有太大區別。 可是,我老是更喜歡預增量,由於直接表達我想說的彷佛更好,而不是依靠優化器來解決。 優化

一樣,減小優化器的工做量可能意味着編譯器運行得更快。 spa


#3樓

我能夠想到後綴比前綴增量慢的狀況: code

想象一下,將具備寄存器A的處理器用做累加器,而且它是許多指令中使用的惟一寄存器(某些小型微控制器實際上就是這樣)。 對象

如今,假設如下程序及其轉換爲假設的程序集: 內存

前綴增量:

a = ++b + c;

; increment b
LD    A, [&b]
INC   A
ST    A, [&b]

; add with c
ADD   A, [&c]

; store in a
ST    A, [&a]

後綴增量:

a = b++ + c;

; load b
LD    A, [&b]

; add with c
ADD   A, [&c]

; store in a
ST    A, [&a]

; increment b
LD    A, [&b]
INC   A
ST    A, [&b]

請注意b的值是如何被強制從新加載的。 使用前綴遞增,編譯器能夠只遞增該值並繼續使用它,可能避免從新加載它,由於所需的值在遞增以後已經存在於寄存器中。 可是,使用後綴增量,編譯器必須處理兩個值,一個是舊值,另外一個是增量值,正如我在上面顯示的那樣,這將致使更多的內存訪問。

固然,若是不使用增量值,例如單個i++; 語句,不管後綴或前綴使用狀況如何,編譯器均可以(而且確實)簡單地生成增量指令。


附帶說明一下,我想提到一個存在b++的表達式不能簡單地用++b轉換爲一個表達式而無需任何額外的努力(例如,經過添加- 1 )。 所以,若是將二者做爲某個表達式的一部分,則將它們進行比較是不正確的。 一般,在表達式中使用b++狀況下,不能使用++b ,所以即便++b可能更有效,也徹底是錯誤的。 若是表達式請求它,固然是例外(例如a = b++ + 1;能夠更改成a = ++b; )。


#4樓

首先:在C中, i++++i之間的區別能夠忽略不計。


到細節。

1.衆所周知的C ++問題: ++i更快

在C ++中,若是i是某種帶有重載增量運算符的對象,則++i效率更高。

爲何?
++i ,對象首先增長,而後能夠做爲const引用傳遞給任何其餘函數。 若是表達式是foo(i++)這是不可能的,由於如今須要在調用foo()以前完成增量,可是須要將舊值傳遞給foo() 。 所以,在對原始文件執行增量運算符以前,編譯器被迫複製i 。 額外的構造函數/析構函數調用是最糟糕的部分。

如上所述,這不適用於基本類型。

2.不爲人知的事實: i++ 可能會更快

若是不須要調用構造函數/析構函數,這在C ++i老是如此, ++ii++應該同樣快,對嗎? 不。它們的速度幾乎同樣快,但可能會有一些細微的差別,大多數其餘應答者都採用了錯誤的方法。

如何能i++更快?
關鍵是數據依賴性。 若是須要從內存中加載該值,則須要對其進行兩個後續操做,使其遞增並使用它。 對於++i ,須要先進行遞增, 而後才能使用該值。 使用i++ ,使用不取決於增量,CPU能夠與增量操做並行執行使用操做。 區別最可能是一個CPU週期,所以它確實能夠忽略不計,可是確實存在。 這是許多人指望的另外一種方式。


#5樓

內容提要:否。

i++可能比++i慢,由於可能須要保存i的舊值以供之後使用,但實際上全部現代編譯器都會對其進行優化。

咱們能夠經過使用++ii++查看此函數的代碼來證實這一點。

$ cat i++.c
extern void g(int i);
void f()
{
    int i;

    for (i = 0; i < 100; i++)
        g(i);

}

這些文件是相同的,除了++ii++

$ diff i++.c ++i.c
6c6
<     for (i = 0; i < 100; i++)
---
>     for (i = 0; i < 100; ++i)

咱們將對其進行編譯,並得到生成的彙編器:

$ gcc -c i++.c ++i.c
$ gcc -S i++.c ++i.c

咱們能夠看到生成的對象文件和彙編文件都是相同的。

$ md5 i++.s ++i.s
MD5 (i++.s) = 90f620dda862cd0205cd5db1f2c8c06e
MD5 (++i.s) = 90f620dda862cd0205cd5db1f2c8c06e

$ md5 *.o
MD5 (++i.o) = dd3ef1408d3a9e4287facccec53f7d22
MD5 (i++.o) = dd3ef1408d3a9e4287facccec53f7d22
相關文章
相關標籤/搜索