コンテンツにスキップ

C言語/inline

出典: フリー教科書『ウィキブックス(Wikibooks)』


C言語におけるinline関数

[編集]

はじめに

[編集]

C言語におけるinlineキーワードは、関数の実行効率を向上させるために導入された重要な機能です。本章では、inline関数の概念、使用方法、そしてC23(ISO/IEC 9899:2024)における最新の仕様について詳しく解説します。

inline関数の基本概念

[編集]

inlineキーワードは、コンパイラに対して「可能であれば、この関数の呼び出しをその関数本体のコードで直接置き換えてください」という指示を出します。これにより、関数呼び出しのオーバーヘッドを削減し、プログラムの実行速度を向上させることができます。

以下は基本的なinline関数の例です:

inline int max(int a, int b) {
    return (a > b) ? a : b;
}

int main() {
    int x = 5, y = 10;
    int result = max(x, y);  // コンパイラによっては、この呼び出しは展開される可能性がある
    return 0;
}

inlineキーワードの文脈による意味の違い

[編集]

inlineキーワードは、宣言の場所や他のキーワードとの組み合わせによって異なる意味を持ちます。

宣言の形式 意味 C23での変更点
inline 関数(ファイルスコープ) コンパイラへの最適化ヒント+外部リンケージを持つ関数の定義 仕様の明確化があり、より一貫した動作
static inline 関数 コンパイラへの最適化ヒント+内部リンケージを持つ関数の定義 基本的な動作は変更なし
extern inline 関数 別の翻訳単位で定義される関数の宣言 挙動の一貫性が向上

次のコード例は、これらの違いを示しています:

// file1.c
inline int func1(int x) { return x * x; }  // 定義と宣言を兼ねる

static inline int func2(int x) { return x + 1; }  // このファイル内でのみ使用可能

extern inline int func3(int x);  // 別の場所で定義された関数の宣言

// file2.c
int func3(int x) { return x - 1; }  // func3の実際の定義

C23におけるinline関数の仕様

[編集]

C23では、inline関数に関する仕様がより明確になり、以前のバージョンで曖昧だった点が解決されています。

// C23でのinline関数の例
#include <stdio.h>
// 関数プロトタイプと定義を兼ねる
inline double calculate_area(double radius) {
    return 3.14159 * radius * radius;
}

// 外部リンケージを持つinline関数の実体の定義
extern inline double calculate_area(double radius);

int main() {
    double area = calculate_area(5.0);
    printf("Area: %f\n", area);
    return 0;
}

inline関数の最適化

[編集]

inline関数は、以下のような場合に最も効果を発揮します:

#include <stdio.h>
inline int square(int x) {
    return x * x;
}

int main() {
    int sum = 0;
    
    // 小さなループ内でのinline関数の使用は効果的
    for (int i = 0; i < 1000; i++) {
        sum += square(i);  // 関数呼び出しのオーバーヘッドを削減
    }
    
    printf("Sum of squares: %d\n", sum);
    return 0;
}

inline関数の複雑な使用例

[編集]

複数のソースファイルでinline関数を共有する場合、ヘッダファイルと実装ファイルの分離が必要となります:

// math_utils.h
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
// プロトタイプ宣言
inline double power(double base, int exponent);

// インライン定義
inline double power(double base, int exponent) {
    double result = 1.0;
    for (int i = 0; i < exponent; i++) {
        result *= base;
    }
    return result;
}

#endif
// math_utils.c
#include "math_utils.h"
// 外部定義
extern inline double power(double base, int exponent);
// main.c
#include <stdio.h>
#include "math_utils.h"
int main() {
    printf("2^10 = %f\n", power(2.0, 10));
    return 0;
}

C23における新機能:属性指定子とinlineの組み合わせ

[編集]

C23では、属性指定子とinlineキーワードの組み合わせがより柔軟になりました:

// C23での属性指定子とinlineの組み合わせ
#include <stdio.h>
[[gnu::always_inline]] inline void critical_operation(int* data, size_t size) {
    for (size_t i = 0; i < size; i++) {
        data[i] = data[i] * 2 + 1;
    }
}

int main() {
    int values[5] = {1, 2, 3, 4, 5};
    critical_operation(values, 5);
    
    for (int i = 0; i < 5; i++) {
        printf("%d ", values[i]);
    }
    printf("\n");
    
    return 0;
}

まとめ

[編集]

inline関数は、適切に使用することでプログラムのパフォーマンスを向上させる強力なツールです。C23では、その仕様がより明確になり、コードの可搬性と予測可能性が向上しています。小さく頻繁に呼び出される関数にinlineを使用することで、関数呼び出しのオーバーヘッドを削減し、より効率的なコードを書くことができます。

しかし、過度なinline関数の使用はコードサイズの増加につながる可能性があるため、パフォーマンスに敏感な部分に限定して使用することが推奨されます。最終的には、コンパイラの最適化オプションとinlineキーワードを適切に組み合わせることで、最良の結果を得ることができるでしょう。