7

これは C99 コードです:

typedef struct expr_t
{
    int n_children; 
    foo data; // Maybe whatever type with unknown alignment
    struct expr_t *children[];
} expr_t;

さて、どのようにメモリを割り当てますか?

expr_t *e = malloc (sizeof (expr_t) + n * sizeof (expr_t *));

また

expr_t *e = malloc (offsetof (expr_t, children) + n * sizeof (expr_t *));

?

柔軟な配列メンバーを持つ型で動作することがsizeof保証されていますか (GCC はそれを受け入れます) ?

4

2 に答える 2

10

expr_t *e = malloc (sizeof (expr_t) + n * sizeof (expr_t *));は C99 で明確に定義されています。C99 仕様 6.7.2.1.16 から:

特殊なケースとして、複数の名前付きメンバーを持つ構造体の最後の要素は、不完全な配列型を持つ場合があります。これは、柔軟な配列メンバーと呼ばれます。ほとんどの場合、柔軟な配列メンバーは無視されます。特に、構造体のサイズは、柔軟な配列メンバーが省略された場合と同じですが、省略が意味するよりも多くの末尾のパディングがある場合があります。

于 2012-10-01T20:58:53.080 に答える
4

コンパイラが柔軟な配列メンバーを持つ構造体の宣言を受け入れる場合、sizeofその構造体の演算子は、柔軟な配列メンバーが存在しないかのように構造体のサイズを生成する必要があります。

このような構造体の正しい割り当ては次のようになります。

expr_t *e = malloc (sizeof(expr_t) + n * sizeof(struct expr_t *));

柔軟な配列メンバーがコンパイラでサポートされていない場合でも、このトリックを実行できます。構造体の配列メンバーを のサイズとして宣言し、 の代わりにアイテムを1割り当てます。n - 1n

于 2012-10-01T21:00:48.850 に答える