パスワードを忘れた? アカウント作成
13859649 journal
日記

quaternionの日記: C言語のポインタの威力と美しさを示せる最も短く理解しやすいコード 32

日記 by quaternion

Quora日本語版に「C言語のポインタの威力と美しさを示せる最も短く理解しやすいコードは何ですか?」という質問があった.ヌル終端文字列のコピー(whileの条件式でコピーするやつ)は自明すぎて面白くないし推奨されるものでもないので,main関数の引数処理を書いてみた.意図したのはargcとargvの更新を一箇所にまとめることだ.

普通はライブラリを使うよねという話もあると思うが,まずい書き方だったたらご批判をこいたい.

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • argv[argc]がNULLであることが保証されているので、
    ポインタアクセスするならargcは不要で、

      while (*++argv) {
        puts(*argv);
      }

    でいいかと。
    あとは、少し冗長ですが

      argv++;
      while (*argv) {
        puts(*argv++);
      }

    と、「argv[0]は読み飛ばしている」ことを明示する方が自分の好みですが、* と ++ の優先順位で悩む人向けには*++argvの方が親切かも。

  • by Anonymous Coward on 2019年03月13日 7時41分 (#3579902)

    mainの引数にconst修飾できるのは処理系定義ではありませんでしたっけ(独自拡張としては許されるが処理系のマニュアルで文書化されていなければならない)。たいていの現実の処理系はリンク時に関数名しか見ないと思いますが、移植性が保証されているわけではないような。

    • by manmos (29892) on 2019年03月13日 10時47分 (#3580020) 日記

      少なくともlinux環境は
      int main(int ,char **);
      ですね。

      argvの中を書き換えてもSEGVは起こりません。

      親コメント
    • by Anonymous Coward

      int hoo(int x); /*プロトタイプ宣言*/

      int hoo(const int x) { /*実装ではconstをつける*/
            /* 省略 */
      }

      と言うコードが書けるぐらいでconst はコンパイル時の静的チェックを行うだけです

      そのメモリがROMのようなread onlyな領域かそうでないかと言う話はOSとかハードウェアの仕事であって
      constにはそれ以上の意味はありません

      • by Anonymous Coward

        int hoo(char** x); /*プロトタイプ宣言*/

        int hoo(const char* const* x) { /*実装ではconstをつける*/
                return x;
        }

        でやってみそ。エラーになるから(少なくともgccとclangではエラーになったし規格上もエラーになるのが正しいはず)。だから
        int main(int argc, const char *const *argv) {
        が通るのは独自拡張と考えるしかない。

        何の関係もない例を持ち出して「意味はありません」とか言われても。

        • by nekopon (1483) on 2019年03月13日 21時53分 (#3580491) 日記
          main関数は引数の数が不定なので、通常のプロトタイプ宣言では書けないのですよ
          親コメント
          • by Anonymous Coward

            その代わり、規格に
            int main(void) { /* ... */ }
            または
            int main(int argc, char *argv[]) { /* ... */ }
            またはこれらと同等(仮引数名が違うだけとかtypedefを使うとか)の宣言か、
            上記以外の処理系定義の何かでなければならないと書かれている。

            const char* const*はchar**と同等とは言えないので、最後の処理系定義の宣言としか考えられない(ただしそれなら文書化されている必要がある)。

        • by Anonymous Coward

          あ、return x;は間違いだけど、これを削除しても結果は変わらない。

  • by Anonymous Coward on 2019年03月13日 9時37分 (#3579966)

    printf("%s\n", *(++argv));

    ってする。

  • by Anonymous Coward on 2019年03月13日 10時02分 (#3579991)

    argvに展開するところやargcを計算するところが凄いんであって、
    それを利用するところは短くて美しいかもしれないけれど凄くはないような。

  • by Anonymous Coward on 2019年03月13日 12時56分 (#3580089)

    数値を16進数の文字に変換するやつ。

    "0123456789ABCDEF"[data & 0x0f]

  • by Anonymous Coward on 2019年03月13日 14時34分 (#3580151)

    const char *const *argv
    を本当に美しいと思う人は、C言語に毒されているだけです
    普通に考えたらこんなコード読みにくくてしょうがないですよ

    そもそもポインタの美しさを示すために
    わざわざ const を付けるのは蛇足でしかありません
    void *p = 0;
    ぐらいで十分です

  • by Anonymous Coward on 2019年03月13日 15時52分 (#3580202)

    よく混乱を招く
    const char * const p
    のpを変更しちゃいかん

    威力はある
    pとqが同じ配列のどれかの要素を指す場合(mallocされたものでもいい)
    pとqの大小比較ができる
    p-qが意味を持つ
    これらはC言語特有の性質

    • by Anonymous Coward

      ポインタとintの変換ができる
      というのもあるな
      ある種のデータ構造を作るのに便利
      ポインタの検索や、二重リンクリストで差分だけを持つやつとか

    • by Anonymous Coward

      ああ、最後は*pね
      失礼しました

    • by Anonymous Coward

      > よく混乱を招く

      自己紹介かな?

      > const char * const p
      > のpを変更しちゃいかん

      このpを変更するのは問題ない。この例で変更できないのは*pと**p

      • by Anonymous Coward

        間違えた
        const char * const* p
        のpは変更しても問題ない。

        • by Anonymous Coward

          お前らコントやってんじゃねえよ(笑)

typodupeerror

UNIXはシンプルである。必要なのはそのシンプルさを理解する素質だけである -- Dennis Ritchie

読み込み中...