C語言:inline,static inline

inline

函數被調用時,需要出棧入棧。當函數頻繁被調用時,則不斷地有函數出棧入棧,會造成棧空間或棧內存的大量消耗。所以引入了inline。

inline: 在函數聲明或定義中函數返回類型前加上關鍵字inline,即可以把函數指定爲內聯函數。
內聯函數: 建議編譯器對一些特殊函數進行內聯擴展(有時稱作在線擴展)。也就是說建議編譯器將指定的函數體插入並取代每一處調用該函數的地方(上下文),從而節省了每次調用函數帶來的額外時間開支。有些類似於宏。

內聯函數與宏調用的比較

  1. 宏調用並不執行類型檢查,甚至連正常參數也不檢查,但是函數調用卻要檢查。
  2. C語言的宏使用的是文本替換,可能導致無法預料的後果,因爲需要重新計算參數和操作順序。
  3. 在宏中的編譯錯誤很難發現,因爲它們引用的是擴展的代碼,而不是程序員鍵入的。
  4. 許多結構體使用宏或者使用不同的語法來表達很難理解。內聯函數使用與普通函數相同的語言,可以隨意的內聯和不內聯。
  5. 內聯代碼的調試信息通常比擴展的宏代碼更有用。

注意:

  1. 關鍵字inline必須與函數定義放在一起才能使函數成爲內聯,僅僅將inline放在函數聲明前面不起任何作用。
  2. inline函數僅僅是一個建議,對編譯器的建議,最後能否真正內聯,還要看編譯器,並不是說聲明瞭內聯就會內聯,聲明內聯只是一個建議而已。
  3. inline的缺點是當函數被多次調用時,代碼替換後,代碼量增加,程序膨脹。所以要慎重使用!尤其要避免如遞歸,循環等。

static inline

c文件中的僅inline函數是不內聯的,因爲沒有static,編譯認他是全局的,因此像普通函數一樣編譯了。
加入static,這樣內部調用函數時,會內聯,而外部調用該函數時,則不會內聯。

在調用這種函數的時候,gcc會在其調用處將其彙編碼展開編譯而不爲這個函數生成獨立的彙編碼。除了以下幾種情況外:

  1. 函數的地址被使用的時候。如通過函數指針對函數進行了間接調用。這種情況下就不得不爲static inline函數生成獨立的彙編碼,否則它沒有自己的地址。
  2. 其他一些無法展開的情況,比如函數本身有遞歸調用自身的行爲等。

extern inline

  1. extern inline函數只會被內聯進去,絕不會生成獨立的彙編碼。即使是通過指針應用或者是遞歸調用也不會讓編譯器爲它生成彙編碼。
  2. extern inline函數允許和外部函數重名,在存在一個外部定義的全局庫函數的情況下,再定義一個同名的extern inline函數也是合法的。
    在這種時候對此函數的 調用會被處理成一個外部引用。另外,

當extern inline函數通過指針應用或者是遞歸調用時,編譯器會將其處理爲外部引用,在鏈接的時候鏈接到外部的同名函數中去(填寫外部函數的地址)。這時如果外部沒有全局的同名函數,就會在鏈接時產生函數未定義的錯誤。

發佈了15 篇原創文章 · 獲贊 30 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章