programing

불완전한 유형에 대한 참조 포인터

prostudy 2022. 7. 16. 13:54
반응형

불완전한 유형에 대한 참조 포인터

저는 이것에 대해 많은 질문을 보았지만, 구체적인 코드 없이 다른 질문을 할 것입니다.유형이 불완전한 원인을 쉽게 파악할 수 있는 방법이 있습니까?제 경우, 누군가 엘스 코드를 사용하고 있고, 헤더가 제대로 되어 있지 않은 것은 확실합니다만, (컴퓨터는 사람의 눈알보다 훨씬 빠르고 잘 하기 때문에) 컴파일러가 "34라인에 X타입이 있다고 생각하지만, 실제로는 없습니다."라고 말하게 할 수 있는 방법이 있습니다.에러 자체는 할당시에만 표시되기 때문에 그다지 도움이 되지 않습니다.

얼마 전 누군가가 실수로 다음과 같은 것을 지정해서 불완전한 활자를 사용했다는 질문을 보았습니다.

struct a {
    int q; 
}; 
struct A *x; 
x->q = 3;

컴파일러는 그것을 알고 있었다.struct A구조물이긴 하지만A 정의되지 struct키워드를 지정합니다.

은 C로, 「C++」의 입니다.(C++)struct비정형입니다(발바닥이 닳을 수 있습니다).「C」를 하고 있는 는, 「C로 합니다.

typedef struct a {
    ...
} a;

하면 .a합니다.struct나중에 이름을 잘못 입력하거나 헤더를 잊어버린 경우 불완전한 형식이 아닌 정의되지 않은 식별자 오류가 나타납니다.

또 다른 가능한 이유는 간접 참조입니다.코드가 현재 c 파일에 포함되지 않은 구조를 참조할 경우 컴파일러는 불만을 제기합니다.

a->b->c // 현재 c파일에 b가 포함되지 않은 경우 오류 발생

할당 시에만 오류가 표시된다는 것은 무슨 뜻입니까?예를 들어 GCC에서는 할당이 표시되지 않습니다.

int main() {
    struct blah *b = 0;
    *b; // this is line 6
}

incompletetype.c:6: error: dereferencing pointer to incomplete type.

에러는 6행입니다.완성되지 않은 활자를 마치 완전한 활자처럼 사용했습니다.그때까지는 괜찮았어요.

이 오류는 유형을 정의하는 헤더를 모두 포함해야 한다는 것입니다.그러나 컴파일러는 어떤 행에 포함시켜야 하는지 짐작할 수 없습니다.함수 이외의 행은 거의 괜찮습니다.시스템상의 모든 텍스트파일을 트롤로 검색하지 않고, 그것을 정의하는 헤더를 검색해, 그것을 포함할 것을 제안합니다.

점,는 potatoswatter(potatoswatter)의 .b정의되어 있습니다.실제로 존재하는 타입을 지정하려고 했을 때,blah .b대부분의 경우 그렇게 어렵지 않을 겁니다.보통 IDE로 할 수 있지만 컴파일러 경고는 문제가 되지 않을 수 있습니다.사용 중인 물건의 정의를 찾을 수 없다면 상당히 악랄한 코드입니다.

뭐가 문제인지 정확히는 모르겠어요.불완전한 유형은 "누락된" 유형이 아닙니다.무능력 유형은 선언되었지만 정의되지 않은 유형입니다(구조체 유형의 경우).정의되지 않은 선언문을 찾는 것은 쉽다.누락된 정의를 찾는 것에 대해서는...컴파일러는 도움이 되지 않습니다.애초 에러의 원인이었기 때문입니다.

C의 불완전한 타입 에러의 주된 이유는 타입명의 오타입니다.이로 인해 컴파일러는 (예를 들어 선언을 정의에 일치시키는 등) 어떤 이름과 다른 이름을 대조할 수 없게 됩니다.하지만 컴파일러는 여기서 당신을 도울 수 없습니다.컴파일러는 오타를 추측하지 않습니다.

이 에러는, 통상, 코드의 구조명과 구조체의 초기화가 다른지를 나타냅니다.따라서, 통상, c는, 배치한 구조체의 이름을 찾아, 원래의 구조가 발견되지 않는 경우는, 통상, 이 이름이 표시됩니다.또는 포인터를 포인터로 가리키면, 에러가 표시됩니다.

A - 솔루션

C언어에 대해서 말하자면, 저는 다음의 선언 코드가 해결책이 될 것이라는 것을 앰피럴리틱하게 알게 되었습니다.

typedef struct ListNode
{
    int data;
    ListNode * prev;
    ListNode * next;
} ListNode;

따라서 일반적으로 유형 정의와 구조 이름 모두에 동일한 이름을 붙입니다.

typedef struct X
{
    // code for additional types here
    X* prev; // reference to pointer
    X* next; // reference to pointer
} X;

B - 문제 샘플

서 다음 은 모두 됩니다.gcc컴파일러를 실행합니다.;

removed->next->prev = removed->prev;

또한 오류 출력에 보고된 비참조 코드에도 동일한 오류가 발생합니다.

>gcc Main.c LinkedList.c -o Main.exe -w
LinkedList.c: In function 'removeFromList':
LinkedList.c:166:18: error: dereferencing pointer to incomplete type 'struct ListNode'
     removed->next->prev = removed->prev;

아래에 나열된 두 헤더 파일 선언에 대해

typedef struct
{
    int data;
    ListNode * prev;
    ListNode * next;
} ListNode;

게다가 이것까지

typedef struct ListNodeType
{
    int data;
    ListNode * prev;
    ListNode * next;
} ListNode;

프로그램 전체의 최적화를 수반하는 시나리오를 제외하고, 코드 코드는 다음과 같이 생성됩니다.

struct foo *bar;
struct foo *test(struct foo *whatever, int blah)
{
  return blah ? whatever: bar;
}

에 을 받지 .struct foo를 포함할 수 있습니다.make 유틸리티는 일반적으로 구조의 완전한 정의가 나타나는 컴파일 유닛을 재컴파일하기 때문에 이러한 변경이 실제로 생성된 코드에 영향을 주지 않더라도 실제로 필요하지 않은 컴파일 유닛에서 완전한 구조 정의를 생략하는 것이 일반적이며, 이러한 누락은 일반적으로 가치가 없습니다.경고의 메시지입니다.

컴파일러는 자동 또는 정적 지속시간을 갖는 유형의 선언 오브젝트, 유형의 멤버를 포함하는 집약 선언 또는 구조 또는 유니언의 멤버에 액세스하는 코드를 처리하는 방법을 알기 위해 완전한 구조 또는 유니언 정의를 가져야 합니다.컴파일러가 위의 조작 중 하나를 실행하는 데 필요한 정보를 가지고 있지 않은 경우 컴파일러는 이에 대해 불평할 수밖에 없습니다.

덧붙여서, 표준에서는 컴파일러가 완전한 유니언 정의를 표시할 필요가 있지만 진단은 필요하지 않은 상황이 하나 더 있습니다. 두 구조가 공통 초기 시퀀스로 시작되며 컴파일러가 구조 중 하나의 포인터를 사용하는 코드를 처리할 때 두 구조를 모두 포함하는 유니언 유형이 표시됩니다.re types를 입력하여 해당 공통 초기 시퀀스의 멤버를 검사합니다.컴파일러는 이러한 코드가 다른 유형의 구조체에 대응하는 멤버에 액세스 하고 있는 것을 인식할 필요가 있습니다.완전한 유니언 타입이 표시되지만 그렇지 않은 경우 표준을 준수하는 컴파일러가 있다면 어떤 컴파일러인지 알 수 없습니다 [gcc는 어느 경우든 부적합 코드를 생성하기 쉽습니다.-fno-strict-aliasing이치노이 경우 양쪽 모두 적합 코드가 생성됩니다.다만, CIS 규칙을 사용하는 코드를, 적합 컴파일러의 올바른 동작을 보증하는 방법으로 기술하고 싶은 경우는, 완전한 유니언 타입의 정의가 보이는 것을 확인할 필요가 있습니다.그렇게 하지 않으면, 컴파일러가 가짜 코드를 사일런트하게 되는 일이 있습니다..

언급URL : https://stackoverflow.com/questions/2700646/dereferencing-pointer-to-incomplete-type

반응형