Namespaces
Variants

inline function specifier

From cppreference.net

inline関数 を宣言します。

目次

構文

inline 関数宣言 (C99以降)

説明

inline 指定子の意図は、コンパイラに対して最適化のヒントを提供することです。例えば 関数インライン展開 のような最適化は、通常、関数の定義が呼び出し元から可視である必要があります。コンパイラは最適化の目的において、 inline 指定子の有無を無視することが可能であり(そして通常無視します)。

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

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

内部リンケージを持つ任意の関数は、他の制限なしに static inline と宣言することができます。

非静的インライン関数は、非constの関数内静的変数を定義できず、ファイルスコープの静的変数を参照できません。

static int x;
inline void f(void)
{
    static int n = 1; // エラー: 非静的インライン関数内の非const静的変数
    int k = x; // エラー: 非静的インライン関数が静的変数にアクセス
}

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

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

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

inline const char *saddr(void) // このファイル内で使用するためのインライン定義
{
    static const char name[] = "saddr";
    return name;
}
int compare_name(void)
{
    return saddr() == saddr(); // 未規定の動作、一方の呼び出しは外部になる可能性がある
}
extern const char *saddr(void); // 外部定義も生成される

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); // 外部定義を提供する

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

#include <stdio.h>
#include "test.h"
extern int f(void);
int main(void)
{
    printf("%d\n", sum(1, 2) + f());
}
**注記**: 提供されたHTMLブロック内のテキストはすべてC++コードであり、指定された翻訳ルール(HTMLタグの非翻訳、 /
/タグ内テキストの非翻訳、C++専門用語の非翻訳)に基づき、翻訳対象となる自然言語テキストは含まれていません。したがって、元のコードは完全に保持されています。

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

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

出力

10

参考文献

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

関連項目

C++ ドキュメント for inline specifier
翻訳内容: - "C++ documentation" → "C++ ドキュメント" - "for" → "for"(C++文脈でそのまま使用) - "inline specifier" → "inline specifier"(C++用語は翻訳せず) HTMLタグ、属性、 タグ内のテキストはすべて原文のまま保持しています。