Dereferenzierungszeiger auf unvollständigen Typ

Lesezeit: 6 Minuten

Nicks Benutzeravatar
Nick

Ich habe viele Fragen dazu gesehen, aber ich werde die Frage ohne spezifischen Code anders stellen. Gibt es eine Möglichkeit LEICHT Bestimmen, was dazu führt, dass der Typ unvollständig ist? In meinem Fall verwende ich den Code eines anderen und ich bin mir absolut sicher, dass ich die Header nicht richtig habe, aber (da Computer dieses Zeug viel schneller und besser machen als menschliche Augäpfel) gibt es eine Möglichkeit, den Compiler dazu zu bringen, es zu sagen , “Hallo du denken Sie haben Typ X in Zeile 34, aber das ist eigentlich so fehlen.” Der Fehler selbst wird nur beim Zuweisen angezeigt, was nicht sehr hilfreich ist.

Benutzeravatar von Potatoswatter
Kartoffelklatsche

Ich habe neulich eine Frage gesehen, bei der jemand versehentlich einen unvollständigen Typ verwendet hat, indem er etwas wie angegeben hat

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

Das wusste der Compiler struct A war eine Struktur, obwohl A völlig undefiniert, aufgrund der struct Stichwort.

Das war in C++, wo eine solche Verwendung von struct ist atypisch (und, wie sich herausstellt, kann es zu einem Fußschuss kommen). In C, wenn Sie dies tun

typedef struct a {
    ...
} a;

dann kannst du verwenden a als Typname und lassen Sie die struct später. Dies führt dazu, dass der Compiler später einen undefinierten Bezeichnerfehler anstelle eines unvollständigen Typs ausgibt, wenn Sie den Namen falsch eingeben oder einen Header vergessen.

Benutzeravatar von Steeven Li
Steeven Li

Ein weiterer möglicher Grund ist eine indirekte Referenz. Wenn ein Code auf eine Struktur verweist, die nicht in der aktuellen C-Datei enthalten ist, beschwert sich der Compiler.

a->b->c //Fehler, wenn b nicht in der aktuellen c-Datei enthalten ist

Was meinst du damit, dass der Fehler nur beim Zuordnen auftaucht? Zum Beispiel auf GCC, ohne dass ein Auftrag in Sicht ist:

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

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

Der Fehler ist In Zeile 6 habe ich einen unvollständigen Typ verwendet, als wäre es ein vollständiger Typ. Mir ging es bis dahin gut.

Der Fehler ist, dass Sie den Header hätten einfügen sollen, der den Typ definiert. Aber der Compiler kann unmöglich erraten, in welcher Zeile das hätte eingefügt werden sollen: Jede Zeile außerhalb einer Funktion wäre ziemlich gut. Es wird auch nicht jede Textdatei auf Ihrem System durchsuchen, nach einem Header suchen, der es definiert, und vorschlagen, dass Sie das einschließen sollten.

Alternativ (guter Punkt, Kartoffelklatsche) liegt der Fehler in der Zeile wo b wurde definiert, als Sie gemeint um einen Typ anzugeben, der tatsächlich existiert, aber tatsächlich angegeben ist blah. Suche nach der Definition der Variablen b sollte in den meisten Fällen nicht allzu schwierig sein. IDEs können das normalerweise für Sie erledigen, Compiler-Warnungen können sich vielleicht nicht darum kümmern. Es ist jedoch ein ziemlich abscheulicher Code, wenn Sie die Definitionen der Dinge, die Sie verwenden, nicht finden können.

Ich verstehe nicht genau, was das Problem ist. Unvollständiger Typ ist nicht der Typ, der “fehlt”. Incompete-Typ ist ein Typ, der ist erklärt aber nicht definiert (bei Strukturtypen). Die nicht-bestimmende Erklärung zu finden ist einfach. Was das Finden der fehlenden Definition betrifft … der Compiler wird Ihnen hier nicht helfen, da dies den Fehler überhaupt erst verursacht hat.

Ein Hauptgrund für unvollständige Typfehler in C sind Tippfehler in Typnamen, die den Compiler daran hindern, einen Namen mit dem anderen abzugleichen (wie beim Abgleich der Deklaration mit der Definition). Aber auch hier kann Ihnen der Compiler nicht weiterhelfen. Compiler machen keine Vermutungen über Tippfehler.

Dieser Fehler zeigt normalerweise an, ob sich der Name Ihrer Struktur von der Initialisierung Ihrer Struktur im Code unterscheidet. Normalerweise findet c also den Namen der von Ihnen eingegebenen Struktur, und wenn die ursprüngliche Struktur nicht gefunden wird, wird dies normalerweise angezeigt, oder Wenn Sie mit einem Zeiger auf diesen Zeiger zeigen, wird der Fehler angezeigt.

  • Zustimmen. Überprüfen Sie zuerst Tippfehler in Strukturdefinitionen im Vergleich zu Deklarationen und allen Typedefs.

    – erik258

    27. November 2017 um 22:02 Uhr

Eine Lösung

Apropos C-Sprache, ich habe gerade ampirisch herausgefunden, dass der folgende Deklarationscode die Lösung sein wird;

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

Daher gebe ich als allgemeine Regel den gleichen Namen sowohl für die Typdefinition als auch für den Namen der Struktur an;

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

B – Problematische Proben

Wobei die folgenden Erklärungen sowohl vom als unvollständig angesehen werden gcc Compiler beim Ausführen der folgenden Anweisung. ;

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

Und ich bekomme denselben Fehler für den in der Fehlerausgabe gemeldeten Dereferenzierungscode;

>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;

Für die beiden Header-Datei unten aufgeführte Erklärungen;

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

Plus dieses;

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

  • Zustimmen. Überprüfen Sie zuerst Tippfehler in Strukturdefinitionen im Vergleich zu Deklarationen und allen Typedefs.

    – erik258

    27. November 2017 um 22:02 Uhr

Benutzeravatar von Supercat
Superkatze

Außerhalb möglicher Szenarien, die eine Optimierung des gesamten Programms beinhalten, wird der Codecode für Folgendes generiert:

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

völlig unbeeinflusst davon, welche Mitglieder struct foo enthalten könnte. Da Make-Dienstprogramme im Allgemeinen jede Kompilierungseinheit neu kompilieren, in der die vollständige Definition einer Struktur erscheint, selbst wenn solche Änderungen den für sie generierten Code nicht wirklich beeinflussen könnten, ist es üblich, vollständige Strukturdefinitionen aus Kompilierungseinheiten wegzulassen, die nicht wirklich benötigt werden sie, und eine solche Unterlassung ist im Allgemeinen keine Warnung wert.

Ein Compiler muss über eine vollständige Struktur- oder Unionsdefinition verfügen, um zu wissen, wie er mit Deklarationsobjekten des Typs mit automatischer oder statischer Dauer, Deklarationen von Aggregaten, die Member des Typs enthalten, oder Code, der auf Member der Struktur oder Union zugreift, umgehen kann. Wenn der Compiler nicht über die erforderlichen Informationen verfügt, um eine der oben genannten Operationen auszuführen, wird er keine andere Wahl haben, als darüber zu kreischen.

Übrigens gibt es eine weitere Situation, in der der Standard einem Compiler erlauben würde, eine vollständige Union-Definition sichtbar zu machen, aber keine Diagnose erfordern würde: wenn zwei Strukturen mit einer gemeinsamen Anfangssequenz beginnen und ein Union-Typ, der beide enthält, sichtbar ist, wenn der Compiler Code verarbeitet, der einen Zeiger eines der Strukturtypen verwendet, um ein Element dieser gemeinsamen Anfangssequenz zu untersuchen, muss der Compiler erkennen, dass ein solcher Code möglicherweise auf das entsprechende Element einer Struktur des anderen Typs zugreift. Ich weiß nicht, welche Compiler dem Standard entsprechen, wenn der vollständige Union-Typ sichtbar ist, aber nicht, wenn dies nicht der Fall ist [gcc is prone to generate non-conforming code in either case unless the -fno-strict-aliasing flag is used, in which case it will generate conforming code in both cases] aber wenn man Code schreiben möchte, der die CIS-Regel so verwendet, dass er ein korrektes Verhalten auf konformen Compilern garantiert, muss man möglicherweise sicherstellen, dass die vollständige Union-Typdefinition sichtbar ist; Wenn Sie dies nicht tun, kann ein Compiler automatisch gefälschten Code generieren.

1416600cookie-checkDereferenzierungszeiger auf unvollständigen Typ

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy