2015-09-22C言語は宣言文が非常に読みにくいことで有名で、後発のGo言語はこれを批判して宣言の構文を変えています。私もずっと読むのが苦手だったのですが、私の頭が悪いのではなく、C言語の仕様がヘン、ということらしい。今まで飽きるほどこの手の解説は書かれてきてるわけですが、自分なりにまとめないと覚えた気がしないので、あえてまとめておきます。ここに書いてある内容は、「C言語ポインタ完全制覇」に詳しく書いてあります。floatなどの基本型から、配列やポインタを派生していくことができます。対象を並べたものが配列で、対象を指し示すのがポインタです。配列やポインタからも配列やポインタを派生できるので、派生パターンは無限に存在します。ポインタ単体配列とか単体ポインタとかいうものはなくて、必ず派生元の型とセットで存在します。void*は単体のポインタみたいな感じもありますが、まあ特殊パターンですよね。ちなみに、C言語で関数は第一級オブジェクトではありませんが、関数も似たような形式を取ります。対象を返す関数、という形で書きます。返す関数(引数はvoid)C言語の関数では関数や配列そのものを返すことが不可能ですが、それぞれのポインタなら返すことができます。(関数を返す関数、配列を返す関数、は作成できないから、そういった宣言は考慮しなくてよい)ここまで、日本語で書いていたら別に変な仕様ではないと思うんですが、C言語で書くとすごく読みづらくなります。ポインタを表す*は識別子の左から修飾し、関数を表す()や配列を表す[]は識別子の右から修飾する、というヘンテコな規則のせいです。(*a)[10];配列へのポインタ、でカッコがでてきて怪しさが出てきました。宣言文では、関数のカッコの他に、演算子(?)の結合順を変更するためにもカッコを使います。おかげで関数宣言でポインタや配列が乱舞する場合は、超絶読みにくくなります。(*(*a(void))[10])(void);実際はここまでの派生型を扱うことは滅多にないと思うんですが、...目眩がしてきます。配列はそもそもポインタ返ししないのが普通なのでたぶん問題になりませんが、関数ポインタを扱う関数はそれなりに登場すると思います。読みづらくても、規則があるからこそコンパイルできるわけで、規則通りにゆっくり辿れば必ず読めます。外側から読む人もいるそうですが、言語公式には内側から渦を巻くように読むのが正解っぽい。Ruleと言うそうな。Rule日本語らしくしたい場合は、最後に順番をひっくり返します。識別子の両隣から読み始めるが、次の順番で結合される。...という風に英語で置き換えてゆく。最後に派生元の型(intとかfloatとか)を付けて終わり。結局何なの?は識別子の両隣からわかるこの規則から、宣言が何を表しているのかは誰でもすぐ解読できます。識別子の両隣を見ればいい。ポインタ*a[10]や*a(void)みたいに両側に何か書いてある時は、配列や関数の方が勝つ。正確に言えば*との間にconstが挟まることもあり得るけれど、大抵は書かないし大丈夫でしょう。読み解くあとは訓練訓練。(*(*a(void))[10])(void);識別子を探して、aを見つける。関数のカッコの方が優先順位が高いのでまずそっちを読む。引数定義の終わりまで読んでしまおう)にぶつかるので、巻き戻ってポインタの*を読む。(にぶつかるので、さっきの)の先に進んで、配列の[10]を読む。)にぶつかるので、巻き戻ってポインタの*を読む。(にぶつかるので、さっきの)の先に進んで、関数の(void)を読む。終端に到達したので、最後にintを読む。和訳したかったら順番をひっくり返そう。返す関数(void)標準ライブラリにあるsignal関数も読みにくさでは有名ですよね。ポインタ)どうやら、関数ポインタを返却したい場合は特に読みにくくなるようです。みたいに説明しているのをたまに見かけるのですが、正確な解説とはいえません。宣言文と同じ構文(ただし識別子の部分が新たな型名の意味になる);こんな風に書いたほうがもう少し正確だと思います。signal関数の宣言は大抵の場合、先にtypedefしてから書かれています。要するに、引数に関数ポインタを取って、戻り値としても同じシグネチャの関数ポインタを返す、というインターフェースだったのです。typedefしないとわからんわ...typedefはこういう、識別子の左右両側に書かれた複雑な派生型を、一つの識別子にまとめ直すという能力があります。intのようなマクロとは違って、もっと複雑なことをやってくれるわけです。複雑な宣言が登場する場合は、こまめにtypedefして読みやすくしていきましょう、という古き良き伝統を書いてこの手の解説は終わります。...でも、後発の言語を見ても分かる通り、ユーザーが(本来必要でない分の)typedefをしないとまともに読めないなんて、C言語の構文はどうかしてると思うのですよ。NAKANOSeesaaブログ×この広告は180日以上新しい記事の投稿がないブログに表示されております。