C言語での複雑な型表記を理解する方法
ブックマークに書いたけど、自分の認識を明確にするため、少し詳しく書いておくことにしてみた。
C言語で、
char *(*(**foo [][8])())[]
みたいな型はどういう意味を持つかは、ぱっと見わかりにくいという話題。
自分にとっての理解するための手順は以下のとおり:
- 0: その型をtypedefする
- 1: typedefで分解する
- 外側の()に注目し、()の内側(= PART)を切り出し、仮の型名NAMEを入れる
- 下に「typedef NAME PART;」を置く
- これを()がなくなるまで繰り返す
- 2: 上左から読んでいく(英語だと逆)
- (ただし、配列の配列は逆から)
//typedef char *(*(**foo [][8])())[]; typedef char *(ret_t)[]; //typedef ret_t *(**foo [][8])(); typedef ret_t *(func_t)(); typedef func_t **foo[][8];
最後のtypedefは、以下のように括弧が付けられ、同様に分解、解釈できる:
//typedef func_t *(*((foo[])[8])); typedef func_t *t1; typedef t1 *t2; typedef t2 t3[8]; typedef t3 foo[];
よって「foo型は、char*配列/のポインタを返す関数/へのポインタのポインタの8要素配列の配列」
英語と日本語では、話順が逆になるけど、この場合は日本語のほうが有利じゃないかな。
全部型の基本構文で分解すると、
////typedef char *(*(**foo [][8])())[]; //typedef char *(ret_t)[]; typedef char *pchar; typedef pchar ret_t[]; // <=> typedef pchar (ret_t)[]; ////typedef ret_t *(**foo [][8])(); //typedef ret_t *(func_t)(); typedef ret_t *pret_t; typedef pret_t func_t(); // <=> typedef pret_t (func_t)(); //typedef func_t **foo[][8]; typedef func_t *t1; typedef t1 *t2; typedef t2 t3[8]; typedef t3 foo[];
型構文の基本は、名前や構造/ポインタ/配列/関数で、その形式も変数宣言や関数宣言と同じ形になるようになっている。typedefの場合、識別子にあたるところが、新たな型名になるので、分解してしまえさえすれば、どんなに複雑な表記だろうと素直に理解できると思う。
以下、コード上に書き下したもの、コンパイルしてエラーが出ないことを確認:
// Understanding complex type declarations in C language. // example: a complex type declaration is: // // char *(*(**foo [][8])())[] // // step 0: typedef the decl // step 1: destruct the type with "typedef"s according to outer-left ()s //typedef char *(*(**foo [][8])())[]; typedef char *(ret_t)[]; //typedef ret_t *(**foo [][8])(); typedef ret_t *(func_t)(); typedef func_t **foo[][8]; // step 2: read from right in English(or from left in Japanese) // // "foo" is array of 8-array of pointer of pointer of // function returning pointer of // array of char pointer. // check test: compile with no warnings and no errors on type checking typedef char *(*(**foo2 [][8])())[]; int main() { foo2* a = 0; foo* b = a; a = b; return 0; }
参考
- Sample: Syntax of The C Programming Language declarator