名前空間
変種
操作

inline 関数指定子

From cppreference.com
< c‎ | language

インライン関数を宣言します。

目次

[編集] 構文

inline 関数宣言 (C99以降)

[編集] 説明

inline 指定子の意図は、コンパイラが最適化を実行するためのヒントとして機能することです。例えば、関数インライン展開などがあり、これには通常、関数呼び出し箇所でその関数の定義が可視である必要があります。コンパイラは、最適化の目的で inline 指定子の有無を無視することができます(そして通常は無視します)。

コンパイラが関数インライン展開を行う場合、その関数の呼び出しを関数本体で置き換えます。これにより、関数呼び出しのオーバーヘッド(スタックにデータを配置し、結果を取得する)を回避できますが、関数のコードが複数回繰り返されるため、実行可能ファイルが大きくなる可能性があります。結果は関数形式マクロに似ていますが、関数内で使用される識別子やマクロは、呼び出し箇所ではなく定義箇所で可視な定義を参照する点が異なります。

インライン展開が行われるかどうかにかかわらず、インライン関数の以下のセマンティクスが保証されます。

内部リンケージを持つ関数は、他に制約なく static inline で宣言できます。

非静的(non-static)インライン関数は、非constの関数ローカルな静的変数を定義できず、ファイルスコープの静的変数を参照することもできません。

static int x;
 
inline void f(void)
{
    static int n = 1; // error: non-const static in a non-static inline function
    int k = x; // error: non-static inline function accesses a static variable
}

非静的関数が inline で宣言された場合、それは同じ翻訳単位内で定義されなければなりません。extern を使用しないインライン定義は外部から可視ではなく、他の翻訳単位が同じ関数を定義することを妨げません。これにより、inline キーワードは、同じプログラムの複数の翻訳単位に含まれる可能性のあるヘッダーファイル内に関数を定義するための static の代替手段となります。

ある関数が一部の翻訳単位で inline で宣言されていても、すべての場所で inline で宣言する必要はありません。最大で1つの翻訳単位が、通常の非インライン非静的関数、または extern inline で宣言された関数を提供することができます。この1つの翻訳単位は、外部定義(external definition)を提供すると言われます。未定義動作を避けるために、外部リンケージを持つ関数の名前が式で使用される場合、プログラム内に1つの外部定義が存在しなければなりません。ODR(One Definition Rule、唯一の定義ルール)を参照してください。

外部リンケージを持つインライン関数のアドレスは常に外部定義のアドレスですが、このアドレスが関数呼び出しに使用される場合、インライン定義(翻訳単位内に存在する場合)と外部定義のどちらが呼び出されるかは未規定です。インライン定義内で定義された静的オブジェクトは、外部定義内で定義された静的オブジェクトとは別個のものです。

inline const char *saddr(void) // the inline definition for use in this file
{
    static const char name[] = "saddr";
    return name;
}
 
int compare_name(void)
{
    return saddr() == saddr(); // unspecified behavior, one call could be external
}
 
extern const char *saddr(void); // an external definition is generated, too

Cプログラムは、関数のインライン版と外部版のどちらが呼び出されるかに依存すべきではありません。そうしない場合、その動作は未規定となります。

[編集] キーワード

inline

[編集] 注釈

inline キーワードはC++から採用されましたが、C++では、関数が inline で宣言された場合、すべての翻訳単位で inline で宣言されなければならず、またインライン関数のすべての定義は全く同じでなければなりません(Cでは定義が異なっていてもよく、その違いによっては未規定の動作になるだけです)。一方、C++では非constの関数ローカルな静的変数が許可されており、インライン関数の異なる定義からのすべての関数ローカルな静的変数はC++では同一ですが、Cでは別個のものです。

[編集]

ヘッダーファイル "test.h"

#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED
 
inline int sum(int a, int b)
{
    return a + b;
}
 
#endif

ソースファイル "sum.c"

#include "test.h"
 
extern inline int sum(int a, int b); // provides external definition

ソースファイル "test1.c"

#include <stdio.h>
#include "test.h"
 
extern int f(void);
 
int main(void)
{
    printf("%d\n", sum(1, 2) + f());
}

ソースファイル "test2.c"

#include "test.h"
 
int f(void)
{
    return sum(3, 4);
}

出力

10

[編集] 参照

  • C23標準 (ISO/IEC 9899:2024)
  • 6.7.4 関数指定子 (p: TBD)
  • C17標準 (ISO/IEC 9899:2018)
  • 6.7.4 関数指定子 (p: TBD)
  • C11標準 (ISO/IEC 9899:2011)
  • 6.7.4 関数指定子 (p: 125-127)
  • C99標準 (ISO/IEC 9899:1999)
  • 6.7.4 関数指定子 (p: 112-113)

[編集] 関連項目

C++ドキュメント inline 指定子
English 日本語 中文(简体) 中文(繁體)