C言語の関数ポインタをtypedefする方法【型定義】
- 作成日: 2022-08-26
- 更新日: 2023-12-25
- カテゴリ: C言語
C言語の関数ポインタをtypedef
C言語では関数ポインタを使うことができます。
そしてtypedefを行うと新しい型が定義できます。
関数ポインタをtypedefで新しい型にしておくと、記述が綺麗になりスッキリします。
関数ポインタは複雑な書き方になっていますが、typedefをうまく使うと簡単にできます。
この記事では関数ポインタをtypedefする方法について解説します。
関連記事
目が覚めるC言語のdo-while文の使い方【ループ処理、初心者向け】
明快!C言語のcontinue文の使い方
君はまだC言語のdefineのすべてを知らない【マクロ、プリプロセス】
プログラミングのポインタをわかりやすく解説【C言語】
コードで見るC言語とC++の7つの違い
関数ポインタの書き方
たとえば関数ポインタは↓のように書きます。
#include <stdio.h>
void func(void) {
printf("Hello\n");
}
int main(void) {
// 関数ポインタ変数funcptrの定義
void (*funcptr)(void) = func;
funcptr(); // Hello
return 0;
}
↑のfuncptr
という変数が関数ポインタです。
すごいキテレツな書き方ですよね。
void (*funcptr)(void)
この関数ポインタfuncptr
には関数func
のアドレスが入っています。
ですのでfuncptr
を呼び出すと関数func
の処理が実行されます。
↑の先頭のvoid
は関数の返り値の型です。
でカッコに入ってアスタリスク(*
)の次のfuncptr
が関数ポインタ変数名。
カッコの中のvoid
は関数の引数の型です。
うーん、キテレツ!
関連記事
C言語の関数ポインタの使い方
C言語の関数ポインタを引数に渡す方法
関数ポインタをtypedefする
先ほどの関数ポインタは↓のようにtypedefできます。
#include <stdio.h>
void func(void) {
printf("Hello\n");
}
// 関数ポインタをtypedefして新しい型MyFuncにする
typedef void (*MyFunc)(void);
int main(void) {
MyFunc funcptr = func;
funcptr(); // Hello
return 0;
}
↑でtypedef
しているところを見てみましょう。
typedef void (*MyFunc)(void);
↑のようになっています。
このように関数ポインタのtypedefはかなり変わった書き方をします。
↑のtypedef
のすぐあとのvoid
が関数の返り値の型です。
そしてカッコの中に入ってアスタリスク(*
)のあとに書かれているMyFunc
が型名です。
このMyFunc
が新しい型です。
そしてカッコを閉じてカッコになってその中のvoid
が関数の引数の型です。
このMyFunc
は新しい型になるので↓のように関数ポインタ変数を書くことができます。
MyFunc funcptr = func;
うーん、すっきりしてて綺麗ですね。
関数ポインタの複雑な書き方がうそみたいにシンプルになりました。
このように関数ポインタはtypedefするとスッキリ書くことができます。
関連記事
C言語の構造体をtypedefする方法
色々な関数ポインタ型
ではもう少しサンプルを紹介します。
さきほどの関数ポインタは返り値もvoidで引数もvoidでした。
返り値や引数がvoidでない場合を見てみましょう。
#include <stdio.h>
// intの返り値、intの引数
typedef int (*MyFunc1)(int);
// char *の返り値、複数の引数
typedef char *(*MyFunc2)(char *, size_t, const char *);
// voidの返り値、MyFunc1の引数
typedef void (*MyFunc3)(MyFunc1);
// 整数を出力する関数
int func1(int n) {
return printf("%d\n", n);
}
// dstにsrcをコピーする関数
char *func2(char *dst, size_t size, const char *src) {
snprintf(dst, size, "%s", src);
return dst;
}
// 引数fnを呼び出す関数
void func3(MyFunc1 fn) {
fn(223);
}
int main(void) {
MyFunc1 funcptr1 = func1;
funcptr1(123); // 123
MyFunc2 funcptr2 = func2;
char buf[100];
printf("%s\n", funcptr2(buf, sizeof buf, "Hello")); // Hello
MyFunc3 funcptr3 = func3;
funcptr3(funcptr1); // 223
return 0;
}
ここまで入り組んでくると解読もけっこう大変になってくるかもしれません。
MyFunc1
はint
を返しint
を引数に取るシンプルな関数ポインタ型です。
MyFunc2
は文字列をコピーするための関数の関数ポインタ型です。
引数が多くなってますがなぜこれらの引数が必要なのかはfunc2()
を見ればわかります。
MyFunc3
は関数ポインタ型を引数に取る関数ポインタ型です。
関数ポインタ型を定義せずにこれを書くと非常にコードが複雑になります。
しかしtypedefしておけばそれほど複雑にはなりません。
おわりに
今回はC言語の関数ポインタのtypedefについて詳しく解説しました。
関数ポインタはtypedefしておくと扱いやすくなります。
typedefを活用してコードを綺麗にしておきましょう。
🦝 < 型を新しく定義
🐭 < typedef!