K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]

新規投稿 | 開設者ホームページへ戻る | ヘルプ

[131] 可変長配列について
投稿者:しゅん
2007/02/20 02:13:25

「センス・オブ・プログラミング」読ませていただきました。 読んで良かったと思いました。 特に3章は共感する所が多くありました。 私もコピペやっちゃうんですよね、そして後で後悔してますね。 新人の頃に読めたらもっと何か違っていたかもと思いもしました。 ところで、可変長配列について説明(P153)がちょっと足りないのでは? 特に「Cに特有の話」の部分にかかります。 typedef struct _VARIABLEARRY { int valMaxIndex; char val[1]; // 1つの配列のインデックス値は本来0だけが有効。 // char val[0]; の記述はコンパイラの実装により異なる。 }VARIABLEARRY; たとえばこの場合 int maxIndex = 10; VARIABLEARRY *pArry; pArry = malloc( sizeof(VARIABLEARRY) + maxIndex ); pArry->valMaxIndex = maxIndex; pArry->val[1] = 'a'; // 配列のインデックス値が宣言した範囲を超えている。 の表記が許される事です。 BASICでは配列のインデックス値が範囲を超えるとエラーです。 Cではこれが間違いではありません。---① また、構造体の最後のメンバを配列にする事でこれが可能である事です。---② typedef struct _VARIABLEARRY { char val[1]; int valMaxIndex; }VARIABLEARRY; とした場合は正しく機能しません。 この2点が「Cに特有の話」である事で、この説明が足りないと思いました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[132] Re:可変長配列について
投稿者:(ぱ)
2007/02/20 02:13:25

>「センス・オブ・プログラミング」読ませていただきました。 >読んで良かったと思いました。 はじめまして。読んでいただきありがとうございます。 >ところで、可変長配列について説明(P153)がちょっと足りないのでは? このテクニックは、私も「ポインタ完全制覇」では説明していますが、 今回の本で必要だったかというとどうかと思います。 Cに特化した話ですし(だからこそ「Cに特有の話」の項になら書いてよいのでは、 というご意見なのだと思いますが)、それに、このテクニックは、使用できる 状況が限定されますし。 このテクニックで可変長配列を実現すると、realloc()で配列を拡張したとき、 構造体本体のアドレスまで変わってしまう可能性があります。 よって、この構造体を指しているポインタがどこかにあるときは、 このテクニックは使えません。 また、可変長配列にできる要素が最後のひとつだけ、という問題もあります。 このテクニックを使う機会は、「その構造体を、連続した塊としてファイルに 吐いたり、ネットワークでどこかに送りたい」というケースに限定されるように 思います。 >Cではこれが間違いではありません。---① 微妙です。少なくとも合法と言い切ることはできません。 C-FAQには以下の記述があります。 http://www.kouno.jp/home/c_faq/c2.html#6 | この技巧は人気がある。ただしDennis Ritchieは「Cの実装への | 根拠のない馴れ馴れしさ」と呼んだ。公式な解釈によると上の | 技巧は Cの 規格に厳密には準拠していないと考えられる。 私も同じように思います。が、ほぼ全ての環境で動くと思うので、 移植性を根拠にこれを使うことをためらう必要はないでしょうけど。 >この2点が「Cに特有の話」である事で、この説明が足りないと思いました。 補足の形で(Webに)載せた方がよいかどうかは、現在思案中です。
[この投稿を含むスレッドを表示] [この投稿を削除]
[133] Re:可変長配列について
投稿者:kit
2007/02/20 02:13:25

> このテクニックで可変長配列を実現すると、realloc()で配列を > 拡張したとき、 これは、この構造体の例よりも もっと合法な使い方である、 単なる可変長配列を realloc() した場合にも起きる問題ですね。 例としては、むしろ、pArry[1] みたいなアクセスでまずいことに なることを挙げた方がいいような気がします。 > 微妙です。少なくとも合法と言い切ることはできません。 この手法は、C99 で合法化されたと考えて良いと思います。 以下参照: http://seclan.dll.jp/c99d/c99d04.htm#dt19990726
[この投稿を含むスレッドを表示] [この投稿を削除]
[134] Re:可変長配列について
投稿者:(ぱ)
2007/02/20 02:13:25

>これは、この構造体の例よりも もっと合法な使い方である、 >単なる可変長配列を realloc() した場合にも起きる問題ですね。 うーん、たとえば折れ線を表現するときに、 typedef struct { int point_count; Point *point; } Polyline; typedef struct { int point_count; Point point[1]; } Polyline; というふたつの実現方法があって、どちらを使うかを考えたとき、 後者の方法だと、pointの数を増減させるたびにPolylineのアドレスが 変わってしまう、ということを言いたかったのですが。 確かにどちらもrealloc()すればpointの指すアドレスは変わりますが、 「pointはPolyline以外誰も指してないけど、Polylineを指してる奴は いっぱいいる」というケースはたぶんたくさんあって、後者の方が 危険度がかなり高いと思います(程度問題にせよ)。 >この手法は、C99 で合法化されたと考えて良いと思います。 >以下参照: >http://seclan.dll.jp/c99d/c99d04.htm#dt19990726 これはそうですね。 そういえばGCCにも、point[0]と書ける拡張機能がありました。
[この投稿を含むスレッドを表示] [この投稿を削除]