typedef宣言
キーワードtypedef を用いて、既存のデータ型に新しい名前をつけることができる。
typedef 既存の型名 新しい型名;
typedef で用いる構文は、「普通の変数宣言の先頭にtypedef と書けば、変数ではなく型の宣言となる。」と覚えておけばよい。たとえば・・
int i; // これは、int型の変数 i の作成 typedef int INTEGER; // これは、INTEGER という新しい型のtypedef宣言 INTEGER foo; // 先にtypedefした INTEGER型の変数 foo の宣言特に #define マクロとごっちゃになってしまう初心者は、ここでしっかりと覚えなおしておくこと。(typedef はマクロではないので,行末には必ずセミコロン(;) が必要.)
typedef の利用法 1 −構造体に名前をつける
構造体の宣言とその作成方法は以下のような方法であった。
// 構造体の宣言 struct employee { char name[12]; double hours; int wage; };struct employee yamada; // struct employee型の変数 yamada を作成構造体 employee を作成するには、そのたびに struct employee とタイプしなければならない。(注1)typedef を使用して、この構造体を EMPLOYEE という新しい型名をつけることができる。(注2)
typedef struct employee { //この場合、タグ(employee)は書いても書かなくてもよい char name[12]; double hours; int wage; } EMPLOYEE;EMPLOYEE yamada; // EMPLOYEE 型の変数 yamada を作成
typedefの利用法 2 −ポインタの作成を容易にする
intを指すポインタを宣言するには int *p; もしくは int* p; と記述する。スペースはアスタリスク(*)の左右どちらにいれてもよいし、いれなくてもよく、単に見た目の問題である。
int* p; と書いたほうが、「『intを指すポインタ』という型の変数 p」 という風に見える、という理由で、こちらの書き方を好む人も多い。ここで問題となるのは、intを指すポインタとして、p1 と p2 を一緒に宣言しようとする場合である。int* p1, p2; と記述すると、int を指すポインタ(int*)の変数 p1 と、int型 (int) の p2 が作成されてしまう。
期待通りに変数を作成するには、 int *p1, *p2; と宣言する必要がある。ポインタを頻繁に扱うプログラムにおいては、ポインタ型として新しい型を typedef 宣言しておくのが便利である。
typedef int *PINT; // 「intを指すポインタ」型として PINT を宣言PINT p1, p2; // 期待通りに「intを指すポインタ」のp1 と p2 を作成できるポインタ型の typedef 宣言はすこし奇妙に見えるかもしれないが、先に書いた、「普通の変数宣言の先頭にtypedef と書けば、変数ではなく型の宣言となる。」というルールを思い出してもらえれば、さほど理解に苦しむことはないと思う。(int *PINT; と書けば、intを指すポインタの PINT という変数ができる。この前に typedef と書けば、それが PINT という新しい型の宣言になる。)
このように、ポインタに対して新しい型名をつけることにより、ポインタの宣言を見やすく、間違いを減らすことができる。
特に、ポインタの配列を使用するときなどには、 PINT pArray[10]; と書けばすむようになり、正しい記述が int* p[10]; だったか int (*p)[10]; だったかなどと悩む必要もなくなる。int p, *q; と書くと、int型の変数 p と、intを指すポインタの q が作成されることは、先にお話したとおりである。この先頭に typedef と書くと、二つの型を同時に typedef 宣言することができる。
typedef int INT, *PINT; INT i; // INT型(intと同じ)の変数 i の作成 PINT p; // PINT型 (INTを指すポインタ)の変数 p の作成。 int* p; と同じtypedefの利用法 3 −構造体と、それを指すポインタ型を同時に宣言
利用法2 の最後の形を、構造体に当てはめると以下のようになる。
// 構造体 CELL型と、CELLを指すポインタ型の // の PCELL型 を同時に宣言 typedef struct cell { char string[10]; struct cell *next; } CELL, *PCELL; PCELL pCell; //pCellは CELL を指すポインタ CELL* pCell; と同じ意味上記は、リストのセルをあらわす構造体として CELL型を、CELLを指すポインタ型として PCELL型を、同時にtyepdef 宣言した例である。
このような typedef 宣言は非常に便利であり、よく利用されるので、C言語のイディオムとしてしっかり覚えておくとよい。
注1)C++の場合には、 タグ名をそのまま型名として利用できるので employee yamada; とだけ記述できる。
注2) タグ名、メンバー名、typedefによる型名には、別々の名前空間が利用される。このため、これらに同じ名前を使用することも可能であるが、混乱を招くことが多いので避けたほうがよい。
![]()