関数ポインタとは?C言語で関数のアドレスを扱う方法をわかりやすく解説

目次

C言語文法解説シリーズ

本記事は「C言語文法解説シリーズ」の1つです。
C言語の文法を、組み込み開発の視点も交えて解説します。

👉 C言語文法解説シリーズ一覧はこちら

関数ポインタとは、関数のアドレスを保持するポインタです。
これにより、関数を変数のように扱うことができます。

最初は分かりにくいですが、仕組みは通常のポインタと同じです。

基本的なポインタの使い方についてはこちらの記事で解説しています。


関数のアドレスとは

変数と同じように、関数にもアドレスがあります。

C
int add(int a, int b)
{
    return a + b;
}

この add は関数名ですが、実は関数のアドレスでもあります。

つまり

add = 関数の場所

という意味になります。

初心者さん

関数にもアドレスあるんですか?

エンジニアくん

変数と同じでメモリに置かれるからね

初心者さん

じゃあポインタで持てる?

エンジニアくん

それが関数ポインタなんだ


関数ポインタの書き方

関数

C
int add(int a, int b);

この関数のポインタはこう書きます。

C
int (*func)(int, int);

意味は

int を返す
(int, int) を受け取る
関数へのポインタ

です。


関数ポインタに代入

C
int (*func)(int, int);

func = add;

これで func は add を指します。


関数ポインタで呼び出し

通常

C
add(1, 2);

関数ポインタ

C
func(1, 2);

または

C
(*func)(1, 2);

どちらでもOKです。

初心者さん

funcって関数なの?

エンジニアくん

関数のアドレスを持ってるんだ

初心者さん

でも呼べるんですね

エンジニアくん

関数を指してるから呼べるんだ


実際の使用例

関数を切り替えることができます。

C
int add(int a, int b) {
    return a + b;
}

int sub(int a, int b) {
    return a - b;
}

int (*func)(int, int);

func = add;
func(5, 3);   // 8

func = sub;
func(5, 3);   // 2

関数を変数のように扱えます。

なぜ関数ポインタを使うのか

関数ポインタを使う最大の理由は、呼び出す関数を切り替えられることです。

例えば通常はこう書きます。

C
if (mode == 0) {
  add(a, b);
} else {
  sub(a, b);
}

関数ポインタを使うとこう書けます。

C
int (*func)(int, int);

if (mode == 0) {
  func = add;
} else {
  func = sub;
}

func(a, b);

呼び出す関数を変数として扱えるようになります。

初心者さん

でもifで分岐すればよくないですか?

エンジニアくん

処理が増えると大変になるんだ

例えば

C
mode 0 → add
mode 1 → sub
mode 2 → mul
mode 3 → div

の場合

通常

C
if (mode == 0) add(a,b);
else if (mode == 1) sub(a,b);
else if (mode == 2) mul(a,b);
else if (mode == 3) div(a,b);

関数ポインタ

C
func = table[mode];
func(a, b);

テーブルで管理できる

C
int (*table[])(int, int) = {
    add,
    sub,
    mul,
    div
};

table[mode](a, b);

これが関数ポインタの強みです。

  • 分岐が消える
  • 追加が簡単
  • 見通しが良い

組み込みでよくある使用例

割り込みハンドラ

C
void (*interrupt_table[])(void) = {
    timer_handler,
    uart_handler,
    adc_handler
};

イベント処理

C
void (*state_table[])(void) = {
    idle,
    run,
    error
};

これらはすべて関数ポインタです。


まとめると

関数ポインタを使う理由は以下です。

  • 呼び出す関数を切り替えられる
  • if文を減らせる
  • テーブルで管理できる
  • 状態遷移と相性が良い
  • 組み込みでよく使う

主な用途

  • コールバック関数
  • 処理の切り替え
  • テーブル駆動処理
  • 割り込みハンドラ

組み込みでは特によく使われます。


よくある混乱ポイント

これ

C
int *func(int, int);

これは関数ポインタではありません。

意味

int* を返す関数

関数ポインタは必ず

C
int (*func)(int, int);

括弧が必要です。


まとめ

関数ポインタとは

  • 関数のアドレスを持つポインタ
  • 関数を変数のように扱える
  • func() で呼び出せる
  • 括弧の位置に注意

この記事が参考になった方へ

C言語の基本文法を一覧で整理しています。

👉 C言語文法解説シリーズ一覧はこちら

技術に関するご相談・開発・自動化ツール作成・記事執筆などのご依頼も承っています。

小さなご相談からでもお気軽にご連絡ください。

お問い合わせはこちら

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする


目次