0

私はpstringと呼ばれるサイズを知っているタイプの文字列を持っています(Pascal 文字列へのウィンク)。struct の代わりに{size, p_bytes}、サイズはメモリ内でバイト配列の前に付けられます。(理由は、概念的にも実際的にも、二重参照を避けるためです。また、構造体とバイト配列の両方の二重ヒープ割り当ても回避します。) ツール func を使用してsizeof(size_t)バイトをさらに割り当て、実際のアドレスへのポインターを返すことでそれを行うことができます。バイト配列の数バイト前のサイズを読み取るマクロを提供します。

代わりに、柔軟な配列メンバーを使用して「柔軟な構造体」を使用して、少し高いレベルでそれを実行したかったのです。

typedef struct {
    size_t   size;
    uint     hash;
    char     bytes[];
} PString;
// constructor:
PString * pstring (char * bytes, size_t size) {...}

(これらの pstring はプールに収容されているため、ハッシュも持っています。) しかし、現在、pstring への適切なアクセスを選択するという一種の形而上学的な問題があります。この問題は、pstrings (通常の文字列と同様) がポインターを介してのみ操作されるという事実に伴います。しかし、指摘されているかどうかにかかわらず、どのようにインターフェースを提供すればよいでしょうか?

  • 文字列は、最も一般的には のような型で暗黙的const char * string;にポイントされるため、pstring 型も「ポイント」するのが自然であり、誰もがそれがポインター型であることを知っています。
  • ただし、構造体を使用する場合、一般的な方法は、変数を暗黙的にポイントするのではなく(タイプをポイントすることによって)、変数を a で明示的に宣言することです*(そして、名前の前に「p_」などを付ける場合もあります)。

では、pstrings のユーザーがセマンティクスを明確にし、実践に慣れるために、ここで何をすべきでしょうか?

いずれにせよ、var が指定され、フィールド アクセスは を通過し->ます。今のところ、ご覧のとおり、私は 2 番目のオプションを選択しました。人々は pstring を として宣言しPString * ps;ます。しかし、私は次の議論に従って変更する準備ができています:

  • pstring var は単に unpointed にすることはできません (構造体のコピーによってバイトが失われるため、通常の文字列よりも少なくなります --> hello segfault)。
  • 「pstring」の「p」は、「pointed」のリマインダーとして扱うことができます。

どう思いますか?

4

3 に答える 3

1

私は柔軟な配列メンバーのファンではありませんが、あなたがそのアプローチを選択したので、それを使用する人にとってより正直で明確であるという理由だけで、ポインターの性質を見えるようにしておくことにします。

于 2012-12-13T14:05:31.100 に答える
0

現在のオプションに固執することをお勧めします(ポインターを明示的にします)。ライブラリのユーザーは、とにかくそれがポインターであることを知っている必要があります (たとえば->、代入を使用すると浅いコピーしか作成されないことを知っているなど)、それを隠そうとしても混乱するだけです。

標準ライブラリもこのアプローチの例を提供しています。FILE型は常に as として使用する必要がありますFILE *

于 2012-12-13T21:20:07.640 に答える