나는 오랫동안 C를 작성하지 않았으므로 이러한 종류의 재귀 적 일을 어떻게 해야하는지 잘 모르겠습니다 ... 각 셀에 다른 셀이 포함되도록하고 싶지만 오류가 발생합니다. "필드 '자식'에 불완전한 유형이 있습니다." 뭐야?
typedef struct Cell {
int isParent;
Cell child;
} Cell;
나는 오랫동안 C를 작성하지 않았으므로 이러한 종류의 재귀 적 일을 어떻게 해야하는지 잘 모르겠습니다 ... 각 셀에 다른 셀이 포함되도록하고 싶지만 오류가 발생합니다. "필드 '자식'에 불완전한 유형이 있습니다." 뭐야?
typedef struct Cell {
int isParent;
Cell child;
} Cell;
답변:
셀은 끝없는 재귀가되므로 다른 셀을 포함 할 수 없습니다.
그러나 셀은 다른 셀에 대한 포인터를 포함 할 수 있습니다.
typedef struct Cell {
bool isParent;
struct Cell* child;
} Cell;
Cell
아직 범위 내에 없습니다.
Cell*
에 cell->child
.
struct
C에서의이 기본적으로 그냥 서로 옆에 자신의 모든 값을 저장, (무한 크기의 메모리 구조로 이어지는, 그 구조체는 너무 다른 하나를 포함해야하기 때문에) 실제로 그 자체로 구조체를 저장하는 것은 불가능하다 .
C에서는 구조 자체를 사용하여 작성하는 typedef를 참조 할 수 없습니다. 다음 테스트 프로그램에서와 같이 구조 이름을 사용해야합니다.
#include <stdio.h>
#include <stdlib.h>
typedef struct Cell {
int cellSeq;
struct Cell* next; /* 'tCell *next' will not work here */
} tCell;
int main(void) {
int i;
tCell *curr;
tCell *first;
tCell *last;
/* Construct linked list, 100 down to 80. */
first = malloc (sizeof (tCell));
last = first;
first->cellSeq = 100;
first->next = NULL;
for (i = 0; i < 20; i++) {
curr = malloc (sizeof (tCell));
curr->cellSeq = last->cellSeq - 1;
curr->next = NULL;
last->next = curr;
last = curr;
}
/* Walk the list, printing sequence numbers. */
curr = first;
while (curr != NULL) {
printf ("Sequence = %d\n", curr->cellSeq);
curr = curr->next;
}
return 0;
}
표준에서는 이것보다 훨씬 더 복잡 할 수도 있지만 컴파일러 struct Cell
는 첫 번째 줄은 typedef
알고 있지만 tCell
마지막 줄까지는 알지 못하는 컴파일러라고 생각할 수 있습니다 .
이 문제를 해결하는 방법이 있습니다.
struct Cell {
bool isParent;
struct Cell* child;
};
struct Cell;
typedef struct Cell Cell;
이렇게 선언하면 컴파일러에게 struct Cell과 plain-ol'-cell이 동일하다는 것을 올바르게 알립니다. 따라서 평소처럼 Cell을 사용할 수 있습니다. 그래도 초기 선언 자체에서 struct Cell을 사용해야합니다.
struct Cell;
다시 쓰 셨어요?
struct Cell
.
struct Cell;
집니다. 그러나, 어떤 이유로 당신이 포함 헤더 파일에 마지막 두 줄 넣으면 전에 당신이 정의 Cell
처음 네 라인 구조체를, 다음 여분는 struct Cell;
nececairy입니다.
typedef struct Cell Cell;
수 Cell
있으며에 대한 별칭을 struct Cell
만듭니다. 컴파일러가 struct Cell { .... }
이전에 본 적이 있는지 여부는 중요하지 않습니다 .
이 게시물이 오래되었다는 것을 알고 있지만 원하는 효과를 얻으려면 다음을 시도해보십시오.
#define TAKE_ADVANTAGE
/* Forward declaration of "struct Cell" as type Cell. */
typedef struct Cell Cell;
#ifdef TAKE_ADVANTAGE
/*
Define Cell structure taking advantage of forward declaration.
*/
struct Cell
{
int isParent;
Cell *child;
};
#else
/*
Or...you could define it as other posters have mentioned without taking
advantage of the forward declaration.
*/
struct Cell
{
int isParent;
struct Cell *child;
};
#endif
/*
Some code here...
*/
/* Use the Cell type. */
Cell newCell;
위의 코드 조각에서 언급 한 두 경우 중 하나에서 반드시 자식 셀 구조를 포인터로 선언해야합니다. 그렇지 않으면 "field 'child'has complete type"오류가 발생합니다. 그 이유는 컴파일러가 사용될 때 할당 할 공간의 양을 알기 위해 "struct Cell"을 정의해야하기 때문입니다.
"struct Cell"의 정의 내에서 "struct Cell"을 사용하려고하면 컴파일러에서 "struct Cell"이 차지하는 공간을 아직 알 수 없습니다. 그러나 컴파일러는 포인터가 차지하는 공간을 이미 알고 있으며 (앞으로 선언하면) "Cell"이 "struct Cell"의 유형이라는 것을 알고 있습니다 (아직 "struct Cell"의 크기는 아직 알지 못합니다) ). 따라서 컴파일러는 정의중인 구조체 내에서 "Cell *"을 정의 할 수 있습니다.
typedef의 기본 정의를 살펴 보겠습니다. typedef는 사용자 정의 또는 내장 된 기존 데이터 유형에 대한 별명을 정의하는 데 사용합니다.
typedef <data_type> <alias>;
예를 들어
typedef int scores;
scores team1 = 99;
앞에서 정의하지 않은 동일한 데이터 유형의 멤버로 인해 자체 참조 구조와 혼동됩니다. 따라서 표준 방식으로 코드를 다음과 같이 작성할 수 있습니다.
//View 1
typedef struct{ bool isParent; struct Cell* child;} Cell;
//View 2
typedef struct{
bool isParent;
struct Cell* child;
} Cell;
//Other Available ways, define stucture and create typedef
struct Cell {
bool isParent;
struct Cell* child;
};
typedef struct Cell Cell;
그러나 마지막 옵션은 일반적으로 원하지 않는 여분의 줄과 단어를 증가시킵니다 (우리는 너무 게으르다;)). 따라서보기 2를 선호하십시오.
typedef
구문에 대한 설명 이 잘못되었습니다 (예 :) typedef int (*foo)(void);
. View 1 및 View 2 예제가 작동하지 않습니다. struct Cell
불완전한 유형을 만들 므로 실제로 child
코드에서 사용할 수 없습니다 .
또 다른 편리한 방법은 다음과 같이 구조 태그를 사용하여 구조를 미리 typedef하는 것입니다.
//declare new type 'Node', as same as struct tag
typedef struct Node Node;
//struct with structure tag 'Node'
struct Node
{
int data;
//pointer to structure with custom type as same as struct tag
Node *nextNode;
};
//another pointer of custom type 'Node', same as struct tag
Node *node;
이전의 모든 대답은 훌륭합니다. 구조에 왜 자체 유형의 인스턴스 (참조가 아닌)를 포함 할 수 없는지에 대한 통찰력을 제공한다고 생각했습니다.
구조는 '값'유형이라는 점에 유의해야합니다. 즉, 실제 값을 포함하므로 구조를 선언 할 때 컴파일러는 인스턴스에 할당 할 메모리 양을 결정해야하므로 모든 멤버를 거치고 추가됩니다. 구조체의 모든 메모리 전체를 알아 내기 위해 메모리를 늘리십시오.하지만 컴파일러가 동일한 구조체의 인스턴스를 내부에서 발견하면 역설입니다 (즉, 구조체 A가 얼마나 많은 메모리를 필요로하는지 알기 위해서는 메모리 양을 결정해야합니다) struct A가 걸립니다!).
그러나 구조체 'A'에 자체 유형의 인스턴스에 대한 '참조'가 포함되어 있으면 참조 유형이 다릅니다. 아직 할당 된 메모리의 양을 모르지만 메모리에 할당 된 메모리의 양을 알고 있습니다 주소 (예 : 참조).
HTH