C語言中文網 目錄

C語言內聯函數

一般來說,調用一個函數流程為:當前調用命令的地址被保存下來,程序流跳轉到所調用的函數并執行該函數,最后跳轉回之前所保存的命令地址。

對于需要經常調用的小函數來說,這大大降低了程序運行效率。所以,C99 新增了內聯函數(inline function)

關鍵字 inline 告訴編譯器,任何地方只要調用內聯函數,就直接把該函數的機器碼插入到調用它的地方。這樣程序執行更有效率,就好像將內聯函數中的語句直接插入到了源代碼文件中需要調用該函數的地方一樣。

要將一個函數定義為內聯函數,需要在函數定義時加上 inline 函數修飾符。例 1 中,swapf()被定義為內聯函數,用來交換兩個浮點變量的值,函數 selection_sortf()會調用內聯函數 swapf()。

【例1】函數 swapf()
// 函數swapf()交換兩個浮點變量的值
// 參數:兩個指向float的指針
// 返回值:無
inline void swapf( float *p1, float *p2 )       // 一個內聯函數
{
   float tmp = *p1; *p1 = *p2; *p2 = tmp;
}
// 函數selection_sortf() 使用 selection-sort算法
// 對float數組進行排序
// 參數:一個float數組,以及其長度
// 返回值:無
void selection_sortf( float a[], int n )        // 對長度為n的數組進行排序
{
  register int i, j, mini;                      // 3個索引變量
  for ( i = 0; i < n - 1; ++i )
  {
    mini = i;                                   // 從索引i開始,尋找最小值
    for ( j = i+1; j < n; ++j )
      if ( a[j] < a[mini] )
        mini = j;
      swapf( a+i, a+mini);                      // 交換最小值元素和索引i元素的值
  }
}

一般來說,不建議把將包含循環的函數定義成內聯函數,例如函數 selection_sortf()。例 1 在 for 循環中使用內聯函數來加速執行效率。

inline 修飾符并非強制性的:編譯器有可能會置之不理。例如,遞歸函數通常不會被編譯成內聯函數。編譯器有權自行決定是否要將有 inline 修飾符的函數編譯成內聯函數。

和其他函數不同的是,在每個用到內聯函數的翻譯單元中,都必須重復定義這個內聯函數。編譯器必須時刻準備好該函數定義,以便在調用它時及時插入內聯代碼。因此,經常在頭文件中定義內聯函數

如果某個翻譯單元內的某個函數的所有聲明都具有 inline 修飾符,而沒有 extern 修飾符,那么該函數具有內聯定義(inline definition)。

內聯定義只針對翻譯單元,它不構成外部定義,因此別的翻譯單元可以包含該函數的外部定義。如果有外部定義附加到內聯定義中,那么編譯器可以自由選擇要使用哪一種定義。

如果使用存儲類修飾符 extern 來聲明一個采用 inline 定義的函數,那么該函數的定義就會是外部的(external)。例如,下面的聲明與 swapf()的定義如果放在例 1 的同一個翻譯單元中,那么 swapf()就具有 extern 定義:
extern void swapf( float *p1, float *p2 );

一旦函數 swapf()具有外部的定義,其他翻譯單元只需要采用普通的函數聲明,就可以調用它。然而,從別的翻譯單元調用函數,將不會被編譯成內聯函數。

內聯函數其實就是普通函數,只不過它們在調用時采用機器碼形式。和普通函數一樣,內聯函數具有自己的地址。如果內聯函數使用到宏,預處理器就會展開宏,展開時所用的宏值,取該內聯函數在源代碼中定義所在位置的宏值。然而,在沒被聲明為 static 的內聯函數中,不應該以靜態存儲周期的方式來定義可修改的對象。

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo