C > gcc內聯函數 inline和__attribute __((always_inline))的區別


我們都知道inline是用來聲明內聯函數的關鍵字。不過在嵌入式應用中,對於ARM片子,采用GCC編譯器,往往有2種聲明內聯函數關鍵字:inline和__attribute __((always_inline)),它們有什么區別呢?

對編譯器

1. inline : 建議編譯器內聯,實際是否內聯由編譯器決定(根據優化等級);

2. __attribute __((always_inline)):強制編譯器將函數當做內聯函數;

 

意義

 

優勢:

1.內聯函數擁有更快的調用速度(減少了函數調用);

2.可以實現把函數代碼集成到調用者處;

3.有利於編譯器優化代碼,減少代碼量(取決於具體情況);

 

缺點:可能導致代碼量膨脹(取決於具體情況);

 

用法

1.inline

__inline__是ISO C90的寫法

寫法1

inline int foo(int *a)
{
  return (*a) ++;
}

 寫法2

inline foo(int *a);

int foo(int *a)
{
  return (*a) ++;
}

 

2. __attribute __((always_inline)) 或者_attribute__ ((__gnu_inline__))

適用於gcc編譯器(參考gcc 參考手冊)

inline void foo(int a) __attribute __((always_inline));

或者

 __attribute __ ((always_inline)) void foo(int a);

 

static , extern與inline

 

 

static inline 表示只會是當前模塊才會調用這個內聯函數;

non-static inline 表示可能有其他模塊會調用這個內聯函數,別的模塊也不能定義這個函數。

如果函數定義中,同時指定inline和extern,該定義僅用於內聯。函數也不會獨自編譯(因為已經被認為可能會被其他模塊調用,會在每個調用處內聯、編譯)

 

與內聯相關的所有函數屬性

 

何時內聯?

 

 

 關於函數屬性 always_inline,一般inline只有特定優化等級才會內聯。而對於聲明always_inline的函數,會一直保持內聯,而且不論有沒有指定優化等級。

 注意declare和define/definition的區別: declare表示聲明,definition表示定義(分配存儲空間);

 

 

 

gnu_inline在gcc 4.1.3以后版本才可用, __GNUC_GNU_INLINE__ or __GNUC_STDC_INLINE__任一已定義才可用。

該屬性應該用於同時聲明為inline的函數。如果一個函數聲明為extern,該定義僅用於inline。用gnu_inline修飾的函數,不會編譯成獨立函數,意思是一定會編譯成內聯函數。

可以用在這種情況,頭文件聲明加上該函數屬性,而庫文件(或.c文件)包含一個副本,但無需extern,頭文件的gnu_inline也會引起內聯。

如果一個函數既不是extern,也不是static,函數被編譯成一個獨立函數,也會盡可能被內聯。

 

不會內聯的情況

關於inline(內聯) 正如gcc手冊描述的那樣(別的編譯器需要查看具體的手冊),gcc 不會真正內聯任何函數,如果使用了 "-fno-inline" 選項,或者如果使用了 "-O0"(優化等級)。當然除此之外,gcc還有其他多種情況不會真正內聯函數。

"-Winline" 選項

 

阻止內聯

阻止inline,可以使用函數屬性 __noinline__ 。即使使用了建議inline關鍵字修飾,__noinline__ 也會阻止真正內聯。

__attribute__((__noinline__)) inline static int f(int a, int b)
{
    return (a + b);
}


main()
{
  // ..
  f(1,2) ; // 該處函數不會真正內聯
}

 

如何判斷是否內聯?

可以通過查看生成的匯編代碼,比如.lst文件,assembly文件。函數調用往往包含入棧、出棧的操作(匯編指令),而內聯函數沒有這些。

 

 參考

1. gcc參考手冊(Using the GNU Compiler Collection For gcc version 4.9.3 );

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM