一文理解|GCC內(nèi)聯(lián)函數(shù)(inline)
我們都知道 inline 是用來聲明內(nèi)聯(lián)函數(shù)的關(guān)鍵字,不過在嵌入式應(yīng)用中,采用 GCC 編譯器,往往有2種聲明內(nèi)聯(lián)函數(shù)關(guān)鍵字:inline 和 __attribute __((always_inline)),它們有什么區(qū)別呢?
對編譯器
inline : 建議編譯器內(nèi)聯(lián),實際是否內(nèi)聯(lián)由編譯器決定(根據(jù)優(yōu)化等級);
__attribute __((always_inline)):強(qiáng)制編譯器將函數(shù)當(dāng)做內(nèi)聯(lián)函數(shù);
意義:

優(yōu)勢:
內(nèi)聯(lián)函數(shù)擁有更快的調(diào)用速度(減少了函數(shù)調(diào)用);
可以實現(xiàn)把函數(shù)代碼集成到調(diào)用者處;
有利于編譯器優(yōu)化代碼,減少代碼量(取決于具體情況);
缺點:
可能導(dǎo)致代碼量膨脹(取決于具體情況);
用法:
inline
__inline__是ISO C90的寫法
寫法1
寫法2
__attribute __((always_inline)) 或者 __attribute__((__gnu_inline__))
適用于 gcc 編譯器(參考 gcc 參考手冊)
或者
static,extern 與 inline

static inline 表示只會是當(dāng)前模塊才會調(diào)用這個內(nèi)聯(lián)函數(shù);
non-static inline 表示可能有其他模塊會調(diào)用這個內(nèi)聯(lián)函數(shù),別的模塊也不能定義這個函數(shù)。
如果函數(shù)定義中,同時指定 inline 和 extern,該定義僅用于內(nèi)聯(lián)。函數(shù)也不會獨自編譯(因為已經(jīng)被認(rèn)為可能會被其他模塊調(diào)用,會在每個調(diào)用處內(nèi)聯(lián)、編譯)
【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書、實戰(zhàn)項目及代碼)??


與內(nèi)聯(lián)相關(guān)的所有函數(shù)屬性

何時內(nèi)聯(lián)?

關(guān)于函數(shù)屬性 always_inline,一般 inline 只有特定優(yōu)化等級才會內(nèi)聯(lián)。而對于聲明 always_inline 的函數(shù),會一直保持內(nèi)聯(lián),而且不論有沒有指定優(yōu)化等級。
注意 declare 和 define/definition 的區(qū)別:declare 表示聲明,definition 表示定義(分配存儲空間);

gnu_inline 在gcc 4.1.3以后版本才可用, __GNUC_GNU_INLINE__ or __GNUC_STDC_INLINE__ 任一已定義才可用。
該屬性應(yīng)該用于同時聲明為 inline 的函數(shù)。如果一個函數(shù)聲明為 extern,該定義僅用于 inline。用 gnu_inline 修飾的函數(shù),不會編譯成獨立函數(shù),意思是一定會編譯成內(nèi)聯(lián)函數(shù)。
可以用在這種情況,頭文件聲明加上該函數(shù)屬性,而庫文件(或.c文件)包含一個副本,但無需 extern,頭文件的 gnu_inline 也會引起內(nèi)聯(lián)。
如果一個函數(shù)既不是 extern,也不是 static,函數(shù)被編譯成一個獨立函數(shù),也會盡可能被內(nèi)聯(lián)。
不會內(nèi)聯(lián)的情況
關(guān)于 inline(內(nèi)聯(lián)) 正如 gcc 手冊描述的那樣(別的編譯器需要查看具體的手冊),gcc 不會真正內(nèi)聯(lián)任何函數(shù),如果使用了 "-fno-inline" 選項,或者如果使用了 "-O0"(優(yōu)化等級)。當(dāng)然除此之外,gcc還有其他多種情況不會真正內(nèi)聯(lián)函數(shù)。
"-Winline" 選項

阻止內(nèi)聯(lián)
阻止inline,可以使用函數(shù)屬性 __noinline__ 。即使使用了建議inline關(guān)鍵字修飾,__noinline__ 也會阻止真正內(nèi)聯(lián)。
如何判斷是否內(nèi)聯(lián)?
可以通過查看生成的匯編代碼,比如 .lst 文件,assembly文件。函數(shù)調(diào)用往往包含入棧、出棧的操作(匯編指令),而內(nèi)聯(lián)函數(shù)沒有這些。
