こんにちは、ナナです。
「typedef」は、データ型に対して別の名前を名付けることができる仕組みです。
C言語のプログラムにおいて「typedef」は使わなくても書くことはできますが、可読性やメンテナンス性を向上させるためには欠かせない機能なのです。
本記事では次の疑問点を解消する内容となっています。
わたしが過去の開発経験からよく使われる「typedef」の活用場面をランキングにしてみました。
統計データを取っているわけではありませんが、「この場面で使うんだな」って知っておくとよいですよ!
では、「typedef」による型定義とは何かを学んでいきましょう。
「typedef」はデータ型を別名で再定義するための機能
まずは「typedef」という機能について知らない方のために、役割と書き方から解説しましょう!
typedefの役割と書き方
「type」とはデータ型であり、「def(define)」とは定義するという意味です。
つまり、「typedef」とはデータ型を定義するための機能です。
ただし、新しいデータ型を作るということではなく、既存のデータ型に別の名前を付けることで扱いやすくするための機能なのです。次のように書きます。
書き方
typedef 既存のデータ型 新しいデータ型名;
使用例
typedef signed char S8;
もともと存在するデータ型に「別の名前」をつける、これが「typedef」の役割です。
「typedef」とはあだ名をつけること
「既存のデータ型に対して、別の名前を付けること」って、そんなことをすることにいったい何の意味があるのでしょうか?
これは皆さんの生活の中でも自然に行われていることであり、便利なものなのです。
皆さんの周りの友達や「アイドル」を呼ぶ時って、「あだ名」を付けて呼ぶことってありますよね。
「あだ名」をなぜ付けるのかって言ったら、呼びやすくなるからですよね。
「typedef」とはプログラム内で利用する名前を、呼びやすくするためのモノなのです。
それではあだ名をつけると便利になるシーンのランキングトップ3を発表していきますよ!
「typedef」の活用場面ランキング第1位:構造体定義
堂々の第1位は「構造体定義」です。
構造体は実践においても使用頻度が高く、構造体を定義するときは「typedef」を使って名前を付けます。
typedefを使った構造体定義方法
構造体の型定義は「typedef」を使って、次のように定義します。
// typedefを使った座標構造体の型定義
typedef struct
{
double latitude; // 緯度
double longitude; // 経度
} Coordinate;
Coordinateが新しく定義した構造体のデータ型名となります。
「typedef」で定義した構造体の変数は、次のように定義します。
// 座標構造体の変数定義
Coordinate pos;
構造体の型定義で「typedef」を使用することにより、変数定義でstructを記述する必要がなくなります。
「構造体」について詳しく知りたい方は『構造体 struct【情報のパッケージ化とそのメリット】』を読んでおくとよいでしょう。
「構造体」は「typedef」が利用される最も代表的な機能です。
構造体定義を行うときは必ず「typedef」を利用するものとして覚えておきましょう!
共用体「union」や列挙型「enum」でも利用される「typedef」
構造体は「ユーザー定義型」と呼ばれる型情報を自由に定義できる仕組みですが、列挙型や共用体を定義するときにも「typedef」は利用されます。
typedef enum
{
E_FRUIT_ORANGE = 0,
E_FRUIT_BANANA,
E_FRUIT_PEACH,
} E_FRUIT;
typedef union
{
char sofa[2];
short bed;
} U_SOFABED;
このように「ユーザー定義型」が登場するシーンで、よく登場するのが「typedef」なのです。
各機能の詳細について知りたい方はリンク先の記事を読んでください。
》列挙型:enum 列挙型【連番の作り方と使いどころを教えます】
》共用体:共用体 union【メモリをシェアする考え方と使い方】
typedefの活用場面ランキング第2位:組み込みデータ型
続いて第2位は「組み込みデータ型」に対する「typedef」の活用です。
「組み込みデータ型」とはC言語にもともと用意されている「char型」や「long型」といったデータ型のことです。
実践的な組み込みデータ型に対する「typedef」の定義方法
実際の開発でもよく使われるのが、次のようなtypedefによる型定義です。
typedef signed char S8;
typedef unsigned char U8;
typedef signed short S16;
typedef unsigned short U16;
typedef signed long S32;
typedef unsigned long U32;
このようにしておくことで、長ったらしいデータ型をさっと書くことができるメリットがあります。
新しく定義された型名を使うと、次のように変数定義をすることができます。
// 型名が長くて使いづらい
unsigned short num1;
// unsigned shortと同じ型だが記述が楽
U16 num2;
正式名称の「unsigned」って長いんですよ!しかも綴りがわかりづらい!
そんな時は「typedef」で定義したわかりやすいあだ名を作っておくと便利なんですね!
typedefの活用場面ランキング第3位:関数ポインタ
続いて第3位にランクインしたのは「関数ポインタ」です。
「関数ポインタの変数定義はややこしい!」
関数ポインタの変数を定義した方は、必ずこのように思います。
プログラムを見てみましょう。「typedef」を使わない関数ポインタ変数は次のように定義されます。う~ん、わかりづらい。
char (*pfunc1)(void);
long (*pfunc2)(long, long);
typedefを使った関数ポインタの型定義
typedefの役割は既存の型に新しい型名を名付けることができる機能でした。このややこしい関数ポインタの型を別の名前に変えてしまえばよいのです。
// 関数ポインタ型を別名でtypedefする
typedef long(* FP_FUNC)(int, short);
このように関数ポインタのデータ型にあだ名をつけておくことで、関数ポインタの変数定義は劇的にわかりやすくなります。
FP_FUNC pfunc = NULL;
関数ポインタについて詳しく知りたい方は、次の記事を読んでおくとよいでしょう。
》参考:関数ポインタ【ポインタを使って関数を呼ぶ仕組み解説】
「データ型名+変数名」の形で関数ポインタの変数を定義することができるようになりました。関数ポインタのデータ型は「typedef」を使って簡略化しましょう!
typedefのまとめ
「typedef」を使うことで様々なデータ型にわかりやすく使いやすい別のあだ名をつけることができます。
これにより「可読性」や「メンテナンス性」を向上させる効果があります。仕事としてのプログラムでは欠かせない要素なんです。