コース一覧
    C言語中級 文字列・構造体
    関数ポインタ

    C言語中級 文字列・構造体

    C言語の文字列と構造体を学び、複数のデータを整理して扱うコースです。

    1
    文字列処理の実践
    01. strlenを自作する15分
    02. strcpyを自作する15分
    03. バッファオーバーフロー体験15分
    04. 文字列を分解する15分
    05. 動的な文字列15分
    06. つくる 名前入力の安全化15分
    07. 第3章クイズ10分
    2
    構造体とポインタ
    01. 構造体ポインタと->15分
    02. 構造体の動的確保15分
    03. 動的な構造体配列15分
    04. 関数ポインタ15分
    05. qsortで並べ替える15分
    06. つくる 動的Student完成15分
    07. 第4章クイズ10分

    関数ポインタ

    関数にも番地がある

    ここまでポインタは、変数や確保した領域を指すものとして扱ってきました。関数も機械語としてメモリに置かれているので、やはり先頭の番地を持っています。配列名が先頭要素の番地になったのと同じように、printf や自作の関数も、名前だけ書くとその番地になります。

    その番地を入れておく変数が関数ポインタです。

    c

    void print_plain(const Student *s);
    
    void (*style)(const Student *) = print_plain;

    読み方は内側からです。(*style) で「style は何かを指すポインタ」、その外側の (const Student *) と先頭の void で「指す先は const Student * を 1 つ受け取って何も返さない関数」となります。style のまわりのカッコは外せません。外して void *style(const Student *) と書くと、「void * を返す関数の宣言」という別物になります。

    呼ぶときは普通の関数と同じ

    代入したあとは、普通の関数名のように書けば呼べます。

    c

    style(&list[i]);

    古い書き方の (*style)(&list[i]) も同じ意味で通ります。今は前者が普通です。

    何がうれしいか

    一覧を表示する処理を考えてください。素の一行で出す形と、点数を星の本数で出す形の 2 通りが欲しくなったとします。関数ポインタが無いと、表示のしかたを if で分けた走査ループを 2 つ書くか、ループの中に if を毎回置くことになります。表示のしかたが 3 つ 4 つと増えるたびに、走査のコードを触ることになります。

    関数ポインタを使うと、走査は 1 つで済みます。

    c

    void print_all(const Student *list, int n, void (*style)(const Student *)) {
        for (int i = 0; i < n; i++) {
            style(&list[i]);
        }
    }

    print_all は「1 人ぶんをどう出すか」を知りません。知らなくてよいことを知らないまま書けるので、表示の種類が増えても print_all は一文字も変わりません。呼ぶ側が渡すものを差し替えるだけです。

    c

    print_all(list, 3, print_plain);
    print_all(list, 3, print_bar);

    「処理そのものを引数として渡す」という考え方は、C に限った話ではありません。他の言語でコールバックや高階関数と呼ばれているものと、やっていることは同じです。次回使う標準ライブラリの qsort も、並べ替えの手順だけを持っていて、大小の決め方はこちらが関数で渡す、という作りになっています。

    要件

    1. print_all の第3引数は void (*)(const Student *) 型の関数ポインタにする
    2. print_all の中では if で表示を分けず、受け取った関数を呼ぶだけにする
    3. 入力が 2 なら print_bar、それ以外なら print_plain を渡す

    ヒント

    関数ポインタの変数は void (*style)(const Student *); の形です。style を囲むカッコは外せません

    関数名をそのまま書くとその関数の番地になります。style = print_bar; のように代入できます

    呼ぶときは style(&list[i]); と、普通の関数と同じ書き方で構いません

    生田 陸人
    監修生田 陸人
    ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
    編集 ゆめさく編集部·公開 2026/08/07

    関連レッスン

    • qsortで並べ替える

      比較関数を書いて qsort で並べ替えられるようになります。

    • つくる 動的Student完成

      構造体と動的メモリで成績管理を作り直せるようになります。

    • 第4章クイズ

      構造体ポインタと関数ポインタの理解を確認します。

    このレッスンに出てくる用語

    意味があいまいなまま進んだ語は、ここから読み直せます。

    • 関数処理に名前を付けて再利用できる単位
    • 変数データに名前をつけて参照する仕組み
    • メモリプログラムとデータを一時保持する高速領域
    • 配列サイズ固定の同型データの集まり
    • 処理計算や代入を表す長方形
    • ループ繰り返し処理。矢印で戻すか専用記号で示す
    • 引数位置引数=順番で渡す。
    • コールバック子から親へ通知するための関数 props
    main.c
    エディタを読み込んでいます

    メモ

    関数ポインタ

    ⌘S で保存