2009-07-15 28 views
0

以下のコードをコンパイルすることはできません(エラーを参照)。訂正に関するアドバイスをいただければ幸いです。C構造体と配列

#include <stdio.h> 

typedef struct { 
    char *fldName; 
    unsigned fldLen; 
} Field; 

typedef struct { 
    char *fldPrompt; 
    unsigned startRow; 
    unsigned startCol; 
} Prompt; 

typedef struct { 
    Field *fields[]; 
    Prompt *prompts[]; 
    unsigned numFlds; <<< invalid field declaration after empty field 
} Form;     <<< in '(incomplete) struct (no name)'. 

Field firstName = { "fName", 12 }; 
Field surName = { "sName", 25 }; 
Field gender = { "gder", 1 }; 

Prompt fn  = { "First Name : ", 4, 10 }; 
Prompt sn  = { "Surname : ", 6, 10 }; 
Prompt gn  = { "Gender  : ", 8, 10 }; 

int main (void) 
{ 
    Form aForm = { { &firstName, &surName, &gender }, 
       { &fn, &sn, &gn}, 
       3 }; <<< Multiple initializers for the same element 
    return 0;    <<< Too many initializers 
} 

答えて

8

すべてのエラーは、誤って構造体内に配列を宣言しているという事実から生じます。 にはがあり、配列のサイズを指定できます。空の括弧を使用することはできません。私。

typedef struct { 
    Field *fields[3]; 
    Prompt *prompts[3]; 
    unsigned numFlds; 
} Form; 

要素数を変更する必要がある場合は、別のものを使用する必要があります。たとえば、両方のフィールドはポインタも持つことができます。

Field **fields; 
Prompt **prompts; 

しかし、その後、あなたは動的にメモリを割り当てるとフリーする必要があります、とあなたは間違いなく構造体を初期化するために集計初期化子を使用することはできません。

+0

パベル:私はあなたの**アドバイスを調査するために様々な要素があることを願っています。 –

4

あなたは境界を指定せずstruct定義で配列を宣言しています。これは不可能です。

typedef struct { 
    Field *fields[]; 
    Prompt *prompts[]; 
    unsigned numFlds; 
} Form; 

あなたは括弧内の数字を指定するか、または代わりに、ポインタ型に変更する必要があり、次のいずれかField **fields;。構造体のサイズは静的であり、コンパイル時には既知であることに注意してください。したがって、構造体の内部に可変サイズの配列を持つことはできません。しかし、可変長配列(ポインタは一定のサイズを持つため)を指すことができます。

+0

Mehrdad:ありがとう。 –

0

次のコードは、[配列のサイズを変更して導入しただけです。

#include <stdio.h> 

typedef struct { 
    char *fldName; 
    unsigned fldLen; 
} Field; 

typedef struct { 
    char *fldPrompt; 
    unsigned startRow; 
    unsigned startCol; 
} Prompt; 

typedef struct { 
    Field *fields[3]; 
    Prompt *prompts[3]; 
    unsigned numFlds; // invalid field declaration after empty field 
} Form;     // in '(incomplete) struct (no name)'. 

Field firstName = { "fName", 12 }; 
Field surName = { "sName", 25 }; 
Field gender = { "gder", 1 }; 

Prompt fn  = { "First Name : ", 4, 10 }; 
Prompt sn  = { "Surname : ", 6, 10 }; 
Prompt gn  = { "Gender  : ", 8, 10 }; 

int main (void) 
{ 
    Form aForm = { { &firstName, &surName, &gender }, 
       { &fn, &sn, &gn}, 
       3 }; // Multiple initializers for the same element 
    return 0;    // Too many initializers 
} 

また、15行目に3を超える値が必要な場合は、ダブルポインタを宣言してメモリを割り当てて使用する必要があります。しかし、それを使用しないときは、割り当てを解除/解放してください。そうしないと、メモリリークが発生します。

+0

Roopesh:ありがとう。私はメモリの割り当て/割り当て解除に注意します! –

0

問題は、ゼロ長配列を初期化できないことです。あなたが宣言についてchague場合

typedef struct { 
    Field *fields[100];  
    Prompt *prompts[100];  
    unsigned numFlds; // <<< invalid field declaration after empty field 
} Form;     // <<< in '(incomplete) struct (no name)'. 

それは動作します。

+0

アラゴルン:ありがとう。 –

2

コンパイラがそのメンバのサイズを知ることができない、つまり構造内の後続メンバのオフセットが不確定であるため、構造体は通常、不完全な型のメンバ(たとえば、次元のない配列)を保持できません。この規則の例外は、最後のメンバであり、不完全な配列型(いわゆるのフレキシブルな配列メンバ)です。

解決策:固定サイズの配列またはポインタを使用します。

+0

Christoph:さまざまな要素が必要なので、ポインタを使用する必要があります。ありがとう。 –

+0

FAMに言及するために+1 –

0

あなたのニーズに最も適したリンクリスト構造のようです。

ところで、プロンプトとフィールドは常に1対1でマッピングされていますか?もしそうなら、あなたは同じ構造にそれらを保存することができます。

+0

Caf:事実上yes。あなたが提案した1つの構造に沿ってこれを再考していました。 –