現(xiàn)在的編譯器有多智能,可能你辛辛苦苦寫的代碼,在編譯器看來(lái)就是幾句廢話,直接被刪除掉。
以 gcc 編譯器為例,編譯的時(shí)候可以加上 -O 選項(xiàng)來(lái)優(yōu)化代碼,優(yōu)化等級(jí)從 0 到 3。
寫一些簡(jiǎn)單的代碼給大家演示下。
#includevoid delay() { for (int i = 0; i < 40000; i++) for (int j = 0; j < 10000; j++); } int main() { printf("helloworld "); delay(); printf("helloworld "); return 0; }
比如在兩條輸出語(yǔ)句之間加上延時(shí),正常的現(xiàn)象是這樣的,很明顯,延時(shí)函數(shù)起了作用。
如果編譯的時(shí)候加上 O1 優(yōu)化選項(xiàng),在編譯器看來(lái),delay 函數(shù)什么事都沒干,可以直接刪掉。
比較兩者的匯編代碼,就能看出開啟 O1 優(yōu)化后,主函數(shù)中沒有調(diào)用 delay,運(yùn)行的現(xiàn)象也確實(shí)沒有延時(shí)。
再比如這樣的代碼,test 函數(shù)直接返回了 1234。
如果不開啟優(yōu)化,主函數(shù)會(huì)調(diào)用 test 函數(shù),如果開啟了優(yōu)化,編譯器會(huì)跳過調(diào)用 test 函數(shù),直接取他的返回值來(lái)使用。
再來(lái)看下 O2 優(yōu)化級(jí)別,比如這個(gè)代碼:
#includevoid test() { printf("helloworld "); } int main() { for (int i = 0; i < 3; i++) { test(); } return 0; }
循環(huán)調(diào)用 test 函數(shù),test 函數(shù)也只是簡(jiǎn)單的使用 printf 輸出字符串。
三份匯編代碼分別對(duì)應(yīng)三個(gè)不同的優(yōu)化級(jí)別,沒開優(yōu)化,O1 優(yōu)化,O2 優(yōu)化。
沒開優(yōu)化的時(shí)候,匯編代碼就是對(duì)應(yīng) C 代碼,有循環(huán),循環(huán)中調(diào)用 test 函數(shù)。
開啟 O1 優(yōu)化,循環(huán)沒了,直接調(diào)用三次 test 函數(shù),因?yàn)檠h(huán)確實(shí)浪費(fèi)時(shí)間。
開啟 O2 優(yōu)化,這次直接把 test 函數(shù)跳過,主函數(shù)中直接調(diào)用 puts 函數(shù),這里的 puts ,就是 printf 優(yōu)化而來(lái),前面講過,使用 printf 直接輸出字符串,編譯器會(huì)默認(rèn)優(yōu)化成 puts。
最后還有一個(gè)級(jí)別是 O3,O3 在 O2 的基礎(chǔ)上優(yōu)化更深。不過關(guān)于 O3 的優(yōu)化并沒有找到簡(jiǎn)短的代碼,這里就不給大家做演示。
在平時(shí)的學(xué)習(xí)中并不建議使用編譯器的優(yōu)化策略,尤其是更高級(jí)別的優(yōu)化,為了提升代碼的運(yùn)行效率,很多時(shí)候編譯器會(huì)調(diào)整代碼結(jié)構(gòu),導(dǎo)致運(yùn)行的結(jié)果跟我們預(yù)期不一樣。作為初學(xué)者,知道有這么回事就行。
-
函數(shù)
+關(guān)注
關(guān)注
3文章
4344瀏覽量
62809 -
代碼
+關(guān)注
關(guān)注
30文章
4809瀏覽量
68817 -
編譯器
+關(guān)注
關(guān)注
1文章
1640瀏覽量
49198
原文標(biāo)題:什么樣的代碼會(huì)被編譯器優(yōu)化
文章出處:【微信號(hào):學(xué)益得智能硬件,微信公眾號(hào):學(xué)益得智能硬件】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論