HN 日本語サマリー

← 一覧へ戻る
プログラミング

C言語の「時計回り/スパイラルルール」

The C ``Clockwise/Spiral Rule'' (c-faq.com)

53 pointsby etrvic42 コメント

要約

C言語の宣言を解析するための「時計回り/スパイラルルール」というテクニックが紹介されています。このルールは、未知の要素から時計回りにスパイラル状に進みながら、遭遇する記号(配列 `[]`、ポインタ `*`、関数 `()`)を特定の英語の定義に置き換えていくことで、複雑な宣言も頭の中で理解できるようにします。例を複数用いて、その適用方法が解説されています。

全文翻訳

(これは、作者である David Anderson が 1994-05-06 に comp.lang.c に投稿したものです。) 「時計回り/スパイラルルール」 David Anderson 著 「時計回り/スパイラルルール」として知られるテクニックがあります。これは、あらゆるCプログラマーが頭の中で任意のC宣言を解析できるようにするものです! 従うべき簡単な3つのステップがあります: 未知の要素から始め、スパイラル/時計回りの方向に移動します。以下の要素に遭遇したら、対応する英語のステートメントに置き換えます: [X] または [] => サイズ X の配列... または サイズ未定義の配列... (type1, type2) => type1 と type2 を渡して... を返す関数 * => ...へのポインタ すべてのトークンがカバーされるまで、スパイラル/時計回りの方向にこれを続けます。常に括弧内のものを先に解決してください! 例1:簡単な宣言 char *str[10]; 私たちが自問する質問:strとは何ですか? 「str は...」 str から始めてスパイラル時計回りの方向に移動すると、最初に見るのは `[` です。これは配列を意味するので... 「str はサイズ 10 の配列で...」 スパイラル時計回りの方向に続け、次に遭遇するのは `*` です。これはポインタを意味するので... 「str はサイズ 10 のポインタで、...へのポインタ」 スパイラル方向に続け、行末(`;`)を見ますが、まだすべてのトークンを訪れていません。続行すると、型 `char` に到達します。したがって... 「str はサイズ 10 のポインタで、char へのポインタ」 これで全てのトークンを「訪問」しました。したがって、完了です! 例2:関数へのポインタ宣言 char *(*fp)( int, float *); 私たちが自問する質問:fpとは何ですか? 「fp は...」 スパイラル時計回りの方向に移動すると、最初に見るのは `)` です。したがって、fp は括弧内にあります。括弧内をスパイラルで続行すると、次に見た文字は `*` です。 「fp は ... へのポインタ」 これで括弧の外に出ました。スパイラル時計回りに続行すると、`(` が見えます。したがって、関数です。 「fp は、int と float ポインタを渡して... を返す関数へのポインタ」 スパイラル方向に続行すると、次に `*` 文字が見えます。 「fp は、int と float ポインタを渡して、... へのポインタを返す関数へのポインタ」 スパイラル方向に続行すると、`;` が見えますが、すべてのトークンを訪問していません。続行すると、型 `char` に到達します。 「fp は、int と float ポインタを渡して、char へのポインタを返す関数へのポインタ」 例3:「究極の」宣言 void (*signal(int, void (*fp)(int)))(int); 私たちが自問する質問:「signal」とは何ですか? signal が括弧内にあることに注意してください。したがって、これを最初に解決する必要があります! 時計回りに移動すると `(` が見えます。したがって... 「signal は int と... を渡す関数」 うーん、この同じルールを `fp` にも使えます。 fp とは? fp も括弧内にあるので、続行すると `*` が見えます。 「fp は ... へのポインタ」 スパイラル時計回りに続行すると、`(` に到達します。 「fp は、int を渡して... を返す関数へのポインタ」 これで関数括弧の外を続行し、`void` が見えます。 「fp は、int を渡して何も返さない(void)関数へのポインタ」 fp の処理が終わったので、`signal` に追いつきましょう。これで... 「signal は int と、int を渡して何も返さない(void)関数へのポインタを渡す関数」 まだ括弧内にいるので、次に見た文字は `*` です。 「signal は int と、int を渡して何も返さない(void)関数へのポインタを渡す関数で、... へのポインタを返す」 括弧内の項目を解決したので、時計回りに続行すると、別の `(` が見えます。 「signal は int と、int を渡して何も返さない(void)関数へのポインタを渡す関数で、int を渡して... を返す関数へのポインタを返す」 最後に続行すると、残っているのは単語 `void` だけです。したがって、signal の最終的な完全な定義は次のようになります。 「signal は int と、int を渡して何も返さない(void)関数へのポインタを渡す関数で、int を渡して何も返さない(void)関数へのポインタを返す」 const および volatile にも同じルールが適用されます。 例えば: const char *chptr; さて、chptr とは? 「chptr は const char へのポインタ」 これはいかがですか: char * const chptr; さて、chptr とは? 「chptr は char への const ポインタ」 最後に: volatile char * const chptr; さて、chptr とは? 「chptr は volatile char への const ポインタ。」 K&R II の 122 ページにある例でこのルールを練習してください。 Copyright © 1993, 1994 David Anderson この著者の名前とこの通知が保持されている限り、この記事は自由に配布できます。