2016-11-19 45 views
-2

我最近碰到一個情況,我寫了下面的代碼:C/C++編譯器優化條件語句多少錢?

for(int i = 0; i < (size - 1); i++) 
{ 
    // do whatever 
} 

// Assume 'size' will be constant during the duration of the for loop 

當看着這個代碼,它讓我不知道究竟是如何在for循環的條件爲每個循環進行評估。具體來說,我很好奇編譯器是否會'優化'每個循環必須完成的任何附加算術。在我的情況下,這個代碼是否會被編譯,使得(size-1)必須爲每個循環迭代進行評估?或者,編譯器足夠聰明地認識到'size'變量不會改變,因此它可以爲每個循環迭代預先計算它。

然後,這讓我想到了一般情況下,你有一個條件語句,可能會指定比必要的更多的操作。

作爲一個例子,如何將以下兩件代碼的編譯:

if(6) 

if(1+1+1+1+1+1) 

int foo = 1; 
if(foo + foo + foo + foo + foo + foo) 

如何聰明的編譯器?上述3種情況會被轉換成相同的機器碼嗎?

雖然我在,但爲什麼不列舉另一個例子。如果你在一個條件下做了一個操作,對最終結果沒有任何影響,編譯器會做什麼?例如:

if(2*(val)) 

// Assume val is an int that can take on any value 

在這個例子中,乘法是完全不必要的。儘管這個案例比我的原始案例看起來更加愚蠢,但問題仍然存在:編譯器是否能夠移除這種不必要的乘法?

問:

  • 多少優化參與條件語句?
  • 它根據編譯器有所不同嗎?
+2

_多少優化_是不應答的。什麼期待?百分之? 50%優化?像「多」這樣的主觀術語? – Tas

+0

@Tas來吧,這是一個懸而未決的問題。評論我列出的一些例子就足夠了。 – Izzo

+0

告訴您的編譯器生成彙編語言列表。通常比較或條件語句是2個彙編語言語句:比較和分支。 –

回答

2

C++語言規範允許編譯器進行任何優化,不會導致預期結果發生可觀察的變化。

如果編譯器可以確定size是恆定的,並且在執行過程中不會改變,它當然可以進行特定的優化。

另外,如果編譯器也可以確定i沒有在循環使用(和它的價值事後又沒有使用),它僅作爲一個計數器,它很可能會改寫回路:

for(int i = 1; i < size; i++) 

因爲這可能會產生較小的代碼。即使以某種方式使用此i,編譯器仍可以進行此更改,然後調整i的所有其他用法,以便可觀察結果仍然相同。

總結:任何事情都會發生。只要可觀察結果相同,編譯器可能會或可能不會做任何優化更改。

2
  • 是的,有很多優化,它是非常複雜的。
  • 它變化的基礎上的編譯器,它也變化的基礎上的編譯選項

檢查 https://meta.stackexchange.com/questions/25840/can-we-stop-recommending-the-dragon-book-please 一些書recomendations如果你真的想了解什麼是編譯器可以做。這是一個非常複雜的主題。

您也可以使用-S選項(gcc/g ++)編譯彙編以查看編譯器實際執行的操作。使用-O3/.../-O0/-O來嘗試不同的優化級別。

4

簡短回答:編譯器是異常聰明,並且通常會優化您提交的那些案例(包括完全忽略不相關的條件)。

理解C++最大的障礙語言新手之一面對的是真正的是他們的代碼和計算機執行什麼之間沒有一對一的關係。該語言的全部目的是創建一個抽象。您正在定義程序的語義,但是計算機沒有責任實際上逐行跟蹤您的C++代碼;事實上,如果這樣做的話,與我們現代計算機所能夠達到的速度相比,它的速度會非常慢。一般來說,除非你有一個微觀優化的原因(遊戲開發人員會想到),最好幾乎完全忽略這個方面的編程,並且相信你的編譯器。編寫一個程序,接受你想要的輸入,並在你想要的計算完成後給出你想要的輸出;並讓你的編譯器在確定物理機器如何完成所有這些事情方面做了很多努力。

是否有例外?當然。有時候你的需求是如此具體以至於你比編譯器知道得更多,並且你最終會進行優化。通常在分析並確定您的瓶頸之後,執行此操作。也沒有理由寫出故意愚蠢的代碼。畢竟,如果你想讓你的程序複製一個50MB的矢量,那麼它會複製一個50MB的矢量。

但是,假設合理的代碼意味着它的樣子,你真的不應該花太多時間擔心這一點。由於現代編譯器優化優化,你會是一個傻瓜,試圖跟上。