2009-07-15 11 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

파벨 (Pavel) : 다양한 요소가 있기를 바랍니다. 그래서 ** 당신의 조언을 조사 할 것입니다. –

4

경계를 지정하지 않고 struct 정의로 배열을 선언했습니다. 이 수 없습니다 :

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

당신은 괄호에 숫자를 지정하거나 대신 포인터 타입으로 변경해야 하나 : Field **fields;. 구조체의 크기는 정적이며 컴파일 타임에 알려져 있으므로 항상 내부에 가변 크기의 배열을 가질 수 없습니다. 그러나 가변 크기 배열 (포인터가 일정한 크기를 가짐)을 가리킬 수 있습니다.

+0

메흐 다드 : 감사합니다. –

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 
} 

또한 Line 15에서 3 이상을 원할 경우에는 이중 포인터로 선언하고 메모리를 할당하여 사용해야합니다. 그러나 사용하지 않을 때는 할당을 해제하거나 해제하십시오. 그렇지 않으면 메모리 누수가 발생합니다.

+0

Roopesh : 감사합니다. 메모리 할당/할당 취소에주의해야합니다! –

0

문제는 길이가 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 +1 –

0

링크드 목록 구조가 사용자의 요구에 가장 적합 할 수 있습니다.

그런데 - 프롬프트와 입력란은 항상 일대일로 매핑되어 있습니까? 그렇다면 동일한 구조로 저장할 수 있습니다.

+0

Caf : 사실 예. 내가 제안한 줄, 즉 하나의 구조를 다시 생각해 보았습니다. –