typedef のちょっとした tips
先日、とあるプログラマーにあるテクニックを紹介してあげた。
ある ID の型を定義するときに、こういった書き方をすることはよくある。
/* ClientId と ServerId はまったくの別物だけど int として定義 */ typedef int ClientId; typedef int ServerId;
しかし、上記の定義の仕方だと、間違えて ClientId に ServerId を代入した場合も特にエラーは発生しない。
/* ここは function.h で定義 */ typedef int ClientId; typedef int ServerId; ClientId getClientId(); ServerId getServerId(); /* ここまで function.h */ /* ここは function.c で定義 */ ClientId getClientId() { ... } ServerId getServerId() { ... } /* ここまで function.h */ /* これは main.c */ int main() { ClientId cid = getServerId(); // 代入できちゃう ... }
これを防ぐにはこんなテクニックがある
/* ここは function.h で定義 */ struct ClientOpaque; typedef struct ClientOpaque* ClientId; struct ServerOpaque; typedef struct ServerOpaque* ServerId; ClientId getClientId(); ServerId getServerId(); /* ここまで function.h */ /* ここは function.c で定義 */ ClientId getClientId() { ... } ServerId getServerId() { ... } /* ここまで function.c */ /* これは main.c */ int main() { ClientId cid = getServerId(); // cannot convert `ServerOpaque*' to `ClientOpaque*' ... }
function.h で struct ClientOpaque; しか定義してないけど、これはオッケー。
使ってるのは ClientOpaque のポインタだけなので、struct ClientOpaque のサイズを知らなくてもコンパイルすることができる。
でもって実際 struct ClientOpaque の中身を操作するのは function.c なので、その中でstruct ClientOpaque の定義を書けばオッケー。
どっかでこのテクニックを知ったんだが、どこで知ったか忘れてしまった・・・
あとこの方法ってなんて名前なんだろう。。。