46

Linuxカーネルコードを探しているときに、次のコードが見つかりました。

   struct thread_info {
    struct task_struct  *task;
    struct exec_domain  *exec_domain;
    unsigned long       flags;
    __u32           status;
    __u32           cpu;
    int         preempt_count;
    mm_segment_t        addr_limit;
    struct restart_block    restart_block;
    void __user     *sysenter_return;
    unsigned long           previous_esp;
    __u8            supervisor_stack[0];
};

最後の変数「supervisor_stack」は長さがゼロの配列であることに注意してください。その使用法は何ですか。前もって感謝します!

4

2 に答える 2

41

これは、柔軟な配列メンバーの C99 以前のバージョンであり、GCC によって拡張機能として提供されています。

C99 の方法は、柔軟な配列メンバーを空の括弧で定義することです。

__u8  supervisor_stack[];

量が構造体に連続して一定ではないデータを格納するために使用されます。メモリは次の形式で割り当てられます

struct foo *ptr = malloc(sizeof *ptr + whatever_is_needed);

6.7.2.1 のパラグラフ 18 で、標準 (ドラフト N1570) はそれらを説明しています。

特殊なケースとして、複数の名前付きメンバーを持つ構造体の最後の要素は、不完全な配列型を持つ場合があります。これは、柔軟な配列メンバーと呼ばれます。ほとんどの場合、柔軟な配列メンバーは無視されます。特に、構造体のサイズは、柔軟な配列メンバーが省略されている場合と同じですが、省略が意味するよりも多くの末尾のパディングがある場合があります。ただし、.(または->) 演算子は、柔軟な配列メンバーを持つ構造体 (へのポインター) である左オペランドと、そのメンバーの右オペランド名を持っている場合、そのメンバーが (同じ要素型の) 最長の配列に置き換えられたかのように動作します。アクセスされるオブジェクトよりも構造体を大きくします。配列のオフセットは、置換配列のオフセットと異なる場合でも、柔軟な配列メンバーのオフセットのままです。この配列に要素がない場合、要素が 1 つあるかのように動作しますが、その要素にアクセスしようとしたり、その要素の 1 つ後ろにポインターを生成しようとした場合の動作は未定義です。

于 2012-07-31T06:00:00.197 に答える
13

可変長配列と呼ばれるものを宣言するのは一般的な C ハックです (ここでは、割り当て時にサイズを定義します)。

例:

struct line {
   int length;
   char contents[0];
 };

 struct line *thisline = (struct line *)
   malloc (sizeof (struct line) + this_length);
 thisline->length = this_length;

このようにして、データの構造定義が得られます。これには、明らかに便利な目的で配列の長さも格納されますが、構造体に通常関連付けられている固定サイズに制約されることはありません。

hereからの例 (詳細情報もあります)

于 2012-07-31T06:03:16.887 に答える