6

最近、「dirent」構造 (dirent.h 内) を調べていて、その定義に少し戸惑いました。

注: このヘッダー ファイルは、私の学校の Solaris マシンのものです。


typedef struct dirent {
    ino_t       d_ino;
    off_t       d_off;
    unsigned short  d_reclen;
    char        d_name[1];
} dirent_t;

特に d_name フィールド。これはオペレーティング システムでどのように機能しますか? null で終了する文字列を格納する必要がある場合、単一の文字の配列は何に役立ちますか? 配列の最初の要素でアドレスを取得できることは知っていますが、まだ混乱しています。明らかに何かが起こっていますが、私には何が起こっているのかわかりません。自宅の Fedora Linux システムでは、このフィールドは単純に次のように定義されています。

char d_name[256];

明らかな理由から、これはより理にかなっています。Solarisヘッダーファイルが構造体を定義する理由を誰かが説明できますか?

4

4 に答える 4

10

他の人が指摘したように、構造体の最後のメンバーにはサイズが設定されていません。ただし、配列は長いですが、実装では、配置したい文字を収容する必要があると判断されます。with のように、構造体にメモリを動的に割り当てることでこれを行いmallocます。

direntただし、メンバーのサイズを 1 として宣言すると便利です。これは、任意の変数によって占有されているメモリの量を簡単に判断できるためdです。

sizeof(dirent) + strlen(d.d_name)

また、サイズ 1 を使用すると、そのような構造体値の受信者が、独自の値を割り当てる代わりに独自の名前を保存しようとするのを思いとどまらせdirentます。Linux の定義を使用すると、任意のdirent値が 255 文字の文字列を受け入れると想定するのが合理的ですが、Solaris はそのdirent値が必要以上の文字を格納することを保証しません。

構造体の最後のメンバーに特別なケースを導入したのは C 99 だったと思います。構造体は、代わりに次のように宣言できます。

typedef struct dirent {
  ino_t d_ino;
  off_t d_off;
  unsigned short d_reclen;
  char d_name[];
} dirent_t;

配列には宣言されたサイズがありません。これは、柔軟な配列メンバーとして知られています。構造体自体が任意の名前を保持できるという錯覚がないことを除いて、Solaris バージョンと同じことを実現します。それを見れば、それ以上のものがあることがわかります。

「柔軟な」宣言を使用すると、占有されるメモリの量は次のように調整されます。

sizeof(dirent) + strlen(d.d_name) + 1

これは、柔軟な配列メンバーが構造体のサイズを考慮していないためです。

特に OS ライブラリ コードで、このような柔軟な宣言が頻繁に見られない理由は、その機能をサポートしていない古いコンパイラとの互換性のためである可能性があります。また、現在の定義を対象とするように記述されたコードとの互換性のためでもあります。これは、構造体のサイズがそのように変更された場合に壊れます。

于 2009-02-18T23:58:47.727 に答える
5

dirent 構造体の直後に、残りの名前を含むメモリ ブロックがメモリ内で続き、そのメモリには d_name フィールドを介してアクセスできます。

于 2009-02-18T22:10:25.270 に答える
5

これは、構造体の末尾にある任意の長さの配列を示すために C で使用されるパターンです。C の配列には境界チェックが組み込まれていないため、コードが d_name で始まる文字列にアクセスしようとすると、構造体の末尾を超えてアクセスが続行されます。readdir()これは、文字列全体と終端の nul を保持するのに十分なメモリを割り当てることに依存します。

于 2009-02-18T22:11:09.793 に答える
1

私にはマイクロ最適化のように見えます。名前は一般的に短いので、使用されないことがわかっているスペースを割り当てる必要はありません。また、Solaris は 255 文字を超える名前をサポートする場合があります。このような構造体を使用するには、必要なスペースを割り当て、想定される配列サイズを無視するだけです。

于 2009-02-18T22:12:38.777 に答える