2013-10-22 63 views
2

C中有很多語句什麼都不做。這意味着刪除它們在程序行爲中將沒有可觀察的變化。允許C編譯器優化掉冗餘語句嗎?

根據C標準,允許C編譯器優化掉這些冗餘語句嗎?

例如,如果我們有這樣的代碼:

#include <stdio.h> 

void f(void); 

int main(void){ 

    printf("a"); 
    f(); // function call statement that provably does nothing 

    printf("b"); 
    1000; // redundant expression statement 

    printf("c"); 
    ; // null statement 

    printf("d"); 
    int x = 1; // assignment statement that is not used 

    printf("e"); 

    return 0; 
} 

void f(void){ 
    1000; // redundant expression statement 
    ; // null statement 
    int x = 1; // assignment statement that is not used 
} 

是編譯器允許生產下同對象的代碼? :

#include <stdio.h> 

void f(void); 

int main(void){ 
    printf("a"); 
    printf("b"); 
    printf("c"); 
    printf("d"); 
    printf("e"); 
    return 0; 
} 

void f(void){ 
} 
+1

是的,閱讀問題:[關於優化'不是一個陳述'在C?](http://stackoverflow.com/questions/13566662/regarding-optimization-for-not-a-statment-in-c)可能會幫助你。 –

+0

函數調用可能不會被刪除..嘗試用'-o2'也 –

+0

@GrijeshChauhan。我的意思是不管,他們*允許*刪除它? – Pacerier

回答

5

C標準(C11 5.1.2.3/4):

在抽象機器中,所有表達式都按照 指定的語義進行評估。一個實際的實現不需要評估 表達式的一部分,如果它可以推斷出它的值沒有被使用,並且沒有產生任何需要的副作用(包括由調用 函數或訪問一個易失性對象引起的任何副作用)。

所以編譯器可以自由地優化掉函數調用,除非函數包含任何「需要」的副作用。措辭有點模糊,可能用不同的方式解釋。但實際上,所有編譯器都會優化空函數。

+0

感謝您查閱標準! – alk

1

是的,如果被告知優化編譯器也可以優先考慮那些什麼都不做的代碼。

但是大多數編譯器默認情況下不會優化。

海合會有一個+三個層次:

-Ox with x = {0, 1, 2, 3} (0 does not optimise and is the default) 

快速測試與海灣合作委員會((Debian的4.4.5-8)4.4.5)表明,已經在OP的例子使用-O1代碼的結果與OP的假設完全相同。


足夠有趣甚至明確return 0-O1在優化掉。

+0

函數調用可能不會被刪除..你用'-o2'試過了嗎? –

+0

@GrijeshChauhan:使用'gcc(Debian 4.4.5-8)4.4.5'已經'-O1'確實導致OP的提議。 – alk

+0

好信息,你更新答案與你的例子... –

0

它強烈依賴於編譯器刪除了什麼,以及它隨之而來的長度。一些編譯器甚至可能會在某些設置下刪除整個靜態函數(不僅僅是他們的調用,但甚至是他們的定義),而其他編譯器可能會非常保守,並且不會刪除任何內容。換句話說,它可能是相當多的對象代碼陳述,或者甚至可能是

int main(int argc, char**argv) { 
    printf("abcde") 
    return 0; 
} 
4

早在上世紀80年代,我的一個朋友告訴我,他寫道,執行的算法計算圓周率的程序,然後打印出來。

當他看着編譯的exe文件,他很驚訝地看到,編譯器已經基本產生:輸出3.14159

總之,C(或任何其他語言)編譯器被允許做任何事情,一切不會改變程序的行爲。

這也適用於爪哇等,其中,JVM採用幾種技術來提高速度(例如,「展開」,而無需通過去循環從而被執行的代碼順序地開銷循環等)