Dereferenzieren des Zeigers auf einen unvollständigen Typfehler in C
-
Ursachen des Fehlers
Dereferenzierung des Zeigers auf unvollständigen Typ
in C - Unvollständige Typen in C
- Referenzieren und Dereferenzieren eines Zeigers in C
-
Lösen Sie den Fehler
Dereferenzierungszeiger auf unvollständigen Typ
in C - Abschluss
Es ist bekannt, dass ein Zeiger verwendet wird, um die Adresse von Werten zu speichern, die in einer Variablen gespeichert sind. Diese Zeigervariable kann auf eine Variable referenziert werden, um ihre Adresse zu erhalten, oder dereferenziert werden, um auf ihren Wert zuzugreifen.
Wenn dieser Zeiger jedoch angezeigt oder bearbeitet werden muss, muss er dereferenziert werden. Wenn diese Dereferenzierung über einen deklarierten, aber nicht definierten Typ erfolgt, wird der Fehler Dereferenzierungszeiger auf unvollständigen Typ
ausgegeben.
Ursachen des Fehlers Dereferenzierung des Zeigers auf unvollständigen Typ
in C
Dieser Fehler wird verursacht, wenn der Compiler auf einen Zeiger stößt, der auf eine Struktur dereferenziert wird. Wenn sich der Compiler in Richtung der Struktur bewegt, findet er sie unvollständig, d. h. nicht richtig definiert.
Der Compiler löst verschiedene Fehler aus, wenn eine undefinierte Struktur aufgerufen wird, um einen Zeiger zu deferenzieren. Die Art des aufgetretenen Fehlers hängt vom verwendeten Compiler ab.
der Dereferenzierungszeiger auf unvollständigen Typ
Fehler im GCC-Compiler
Eine undefinierte Struktur sieht beispielsweise so aus:
struct circle {
int length;
};
int main() {
struct round *x = 0;
*x;
}
Im obigen C-Programm kann beobachtet werden, dass eine Struktur Kreis
konstruiert wird, aber die innerhalb der Funktion Haupt
aufgerufene Struktur hat den Namen Runde
.
Innerhalb der Funktion main
wird aus der Struktur round
ein Objektzeiger *x
erzeugt. Zuletzt wird das Zeigerobjekt aufgerufen.
Hier wird eine unvollständige Struktur verwendet, als wäre sie eine vollständige Struktur, was dazu führt, dass der Compiler den Fehler auslöst.
1035906452/source.c: In function 'main':
1035906452/source.c:6:5: error: dereferencing pointer to incomplete type 'struct round'
*x;
^~
Es ist zu beobachten, dass der Compiler den Fehler Dereferenzierung des Zeigers auf unvollständigen Typ
ausgibt.
Normalerweise findet C den Namen der eingegebenen Struktur; Wenn die ursprüngliche Struktur nicht gefunden wird, wird dies normalerweise angezeigt. Es wird auch angezeigt, wenn Sie mit einem Zeiger auf diesen Zeiger zeigen.
Dieser Fehler tritt normalerweise auf, wenn sich der Name Ihrer Struktur von der Initialisierung Ihrer Struktur im Code unterscheidet.
Eine Struktur kann auch Fehler auslösen, wenn ihr ein Alias zugewiesen wird, den der Compiler nicht lesen kann, aber das passiert nicht bei jedem Compiler.
der Dereferenzierungszeiger auf unvollständigen Typ
Fehler im Clang-Compiler
Dies tritt auf, wenn derselbe Code durch einen Clang-Compiler ausgeführt wird.
1790191360/source.c:6:5: error: incomplete type 'struct round' where a complete type is required
*x;
^
1790191360/source.c:5:12: note: forward declaration of 'struct round'
struct round *x = 0;
^
1790191360/source.c:6:5: warning: expression result unused [-Wunused-value]
*x;
^~
1 warning and 1 error generated.
Hier ruft der Compiler die unvollständige Struktur auf, lässt aber den dereferenzierten Zeiger als Warnung statt als Fehler zurück.
Um zu verstehen, warum der Fehler Dereferenzierung des Zeigers auf unvollständigen Typ
auftritt, müssen Sie zwei Konzepte kennen.
- Was sind unvollständige Typen?
- Was bedeutet das Dereferenzieren eines Zeigers?
Unvollständige Typen in C
Ein deklarierter, aber nicht angegebener Typ ist unvollständig (im Fall von Strukturtypen).
Tippfehler in Typnamen, die den Compiler daran hindern, einen Namen dem anderen zuzuordnen, sind eine häufige Ursache für unvollständige Typfehler in der Sprache C (z. B. beim Abgleich der Deklaration mit der Definition).
Es ist ein Irrtum zu glauben, dass ein unvollständiger Typ ein fehlender Typ ist. Unvollständige Typen können auch außerhalb von struct auftreten.
Drei Szenarien verursachen unvollständigen Typ:
- Ein Strukturtyp ohne Mitglieder.
- Ein Gewerkschaftstyp ohne Mitglieder.
- Ein Array, das deklariert wird, aber kein Element eingefügt wird.
Erstellen Sie einen unvollständigen Typ und definieren Sie ihn
Eine ähnliche Struktur oder ein ähnlicher Typ
muss mit den fehlenden Informationen angegeben werden, um einen unvollständigen Typ zu vervollständigen.
Die Erstellung und Vervollständigung der unvollständigen Typen wird in den folgenden Beispielen demonstriert.
Deklarieren Sie einen Strukturtyp, aber lassen Sie die Mitglieder weg, um einen unvollständigen Strukturtyp zu erzeugen. Der x
-Zeiger in dieser Abbildung zeigt auf einen unvollständigen Strukturtyp namens library
.
struct library *x;
Deklarieren Sie denselben Strukturtyp später im selben Bereich mit seinen bereitgestellten Membern, um einen unvollständigen Strukturtyp zu vervollständigen.
struct library {
int book_id;
char book_name[50];
}
Um ein Array unvollständiger Typen zu erstellen, deklarieren Sie einen Array-Typ, ohne seine Wiederholungsanzahl anzugeben. Zum Beispiel:
char book_name[]; /* book_name has incomplete type */
Deklarieren Sie denselben Namen später im selben Gültigkeitsbereich mit festgelegtem Wiederholungszähler, um einen unvollständigen Array-Typ zu beenden.
char book_name[25]; /* book_name now has complete type */
Sobald wir verstanden haben, wie unvollständige Typen vervollständigt werden, können wir zum zweiten Teil übergehen, um den Fehler Dereferenzierung des Zeigers auf unvollständigen Typ
zu beheben.
Referenzieren und Dereferenzieren eines Zeigers in C
Die Funktion eines Zeigers besteht darin, die Adresse eines Werts zu speichern, was bedeutet, dass er eine Referenz auf etwas speichert. Das Objekt, auf das ein Zeiger zeigt, wird Pointee genannt.
Referenzieren eines Zeigers in C
Es gibt zwei unterschiedliche Phasen, die beim Zuordnen eines Zeigers und eines Pointees, auf den er zeigen wird, beteiligt sind. Man kann sich die Pointer/Pointee-Struktur so vorstellen, als hätte sie zwei Operationsebenen.
Alles muss auf beiden Ebenen eingerichtet werden, damit es funktioniert. Der häufigste Fehler besteht darin, sich auf das Schreiben von Code zu konzentrieren, der die Pointer-Ebene manipuliert, während die Einrichtung der Pointee-Ebene vernachlässigt wird.
Zeigeroperationen, die die Pointees nicht kontaktieren, werden manchmal als “flache” Operationen bezeichnet, während diejenigen, die dies tun, als “tiefe” Operationen bezeichnet werden.
Betrachten Sie den folgenden Code:
Innerhalb der Funktion main
wird ein Zeiger ptr_a
erstellt. Dieser Zeiger wird erstellt, kann aber nichts speichern, es sei denn, es wird ein pointee
oder ein Speicherblock zugewiesen.
Die Speicherzuweisung erfolgt durch malloc
, und die angegebene Grösse entspricht dem Datentyp int
.
void main() {
int* ptr_a; // Allocate the pointer
ptr_a = malloc(
sizeof(int)); // Allocate an int pointee, and set ptr_a to point to it
}
C++-Code:
int main() {
int* ptr_a; // Allocate the pointer ptr_a
ptr_a = new int; // Allocate an int pointee, and set ptr_a to point to it
}
Dereferenzieren eines Zeigers in C
Dereferenzierungsoperationen beginnen am Pointer und folgen bis zum Pointee. Das Ziel könnte darin bestehen, den Pointee-Zustand zu untersuchen oder zu modifizieren.
Ein Zeiger kann nur dereferenziert werden, wenn er einen Pointee hat; Der Pointee muss ebenfalls zugewiesen werden, bevor der Pointer dazu gebracht werden kann, darauf zu zeigen. Das Vergessen, den Pointee einzurichten, ist der häufigste Fehler in Pointer-Programmen.
Fehler im Code, einen Zeiger erfolgreich zu dereferenzieren, ist der häufigste Laufzeitabsturz. Das Laufzeitsystem in Java kennzeichnet das Problem unsachgemäßer Dereferenzierungen mit geringfügigen Warnungen.
In kompilierten Sprachen wie C und C++ kann eine fehlerhafte Dereferenzierung einen Absturz oder eine spontane Speicherbeschädigung verursachen. Dies macht es schwierig, Zeigerprobleme in kompilierten Sprachen zu finden.
C-Code:
Sobald der Speicher allokiert ist und auf den Pointer ptr_a
zeigt, wird ein Wert darin gespeichert, indem er dereferenziert wird.
void main() {
int* ptr_a;
ptr_a = malloc(
sizeof(int)); // Allocate an int pointee, and set ptr_a to point to it
*ptr_a = 42; // Dereference ptr_a to store 42 in its pointee
}
C++-Code:
int main() {
int* ptr_a; // Allocate the pointers
ptr_a = new int; // Allocate an int pointee, and set ptr_a to point to it
*ptr_a = 42; // Dereference ptr_a to store 42 in its pointee
}
Gemeinsame Zeiger in C
Wenn zwei Pointer demselben Pointee zugewiesen werden, zeigen sie beide dorthin. Als Ergebnis zeigt y
auf denselben Punkt wie x
, wenn y = x
.
Die Pointees sind von der Zeigerzuweisung nicht betroffen.
Es modifiziert nur einen Zeiger, um die gleiche Referenz wie ein anderer zu teilen. Nach der Zeigerzuweisung werden die beiden Zeiger als den Pointee “gemeinsam” betrachtet.
C-Code:
void main() {
int* ptr_a;
int* ptr_b;
ptr_a = malloc(sizeof(int));
*ptr_a = 42;
*ptr_b = 13; // CRASH -- ptr_b does not have a pointee yet
ptr_b = ptr_a; // Pointer assignment sets ptr_b to point to ptr_a's pointee
*ptr_b = 13; // Dereference ptr_b to store 13 in its (shared) pointee
}
Wir haben die beiden Konzepte zur Lösung des Fehlers Dereferenzierung des Zeigers auf unvollständigen Typ
verstanden. Wir werden uns nun die Codes ansehen, die auf den Fehler stoßen, und wie das Problem gelöst werden kann.
Lösen Sie den Fehler Dereferenzierungszeiger auf unvollständigen Typ
in C
Das folgende Programm hat eine Struktur Rechteck
mit einem ganzzahligen Element Länge
. Der Name des Structs unterscheidet sich bewusst von dem innerhalb der Funktion main
, um einen unvollständigen Typ zu erzeugen.
Innerhalb der main
-Funktion wird der Pointer *a
erstellt und Speicher der Größe des struct rectangle
zugewiesen, und dann wird darauf gezeigt.
Dann wird der Zeiger verwendet, um das Struct-Member length
zu dereferenzieren, um einen Wert darin zu speichern. Da die Struktur vom Typ unvollständig ist, muss sie einen Fehler Dereferenzierungszeiger auf unvollständigen Typ
ausgeben.
#include <stdio.h>
#include <stdlib.h>
struct rectangle {
int length;
};
int main() {
struct square *a;
a = (struct rectngle *)malloc(sizeof(struct rectngle));
a->length = 33;
printf("%d", *a);
}
Ausgang:
1647679200/source.c: In function 'main':
1647679200/source.c:10:38: error: invalid application of 'sizeof' to incomplete type 'struct rectngle'
a = (struct rectngle*)malloc(sizeof(struct rectngle));
^~~~~~
1647679200/source.c:11:3: error: dereferencing pointer to incomplete type 'struct square'
a->length = 33;
^~
Der unvollständige Typ muss vervollständigt werden, um dieses Problem zu beheben, was in diesem Fall die Struktur rectngle
ist.
Diese Änderungen müssen vorgenommen werden, um eine unvollständige Struktur zu vervollständigen und ihre Mitglieder durch einen Zeiger innerhalb der Funktion main
zu dereferenzieren.
#include <stdio.h>
#include <stdlib.h>
struct rectangle { // a struct rectngle is created
int length;
};
int main() {
struct rectangle *a; // name of struct inside main() is same as above struct
a = (struct rectangle *)malloc(sizeof(
struct rectangle)); /*pointer allocated memory and
pointer
to pointer 'a'. */
a->length = 33; // pointer deferenced.
printf("%d", *a); // value of pointer dereferenced
}
Ausgang:
33
Abschluss
Dieser Artikel beleuchtet den Fehler, der durch die Dereferenzierung des Zeigers auf einen unvollständigen Typ entsteht. Nachdem der Leser diesen Artikel gelesen hat, kann er leicht auf Zeiger verweisen und sie referenzieren und unvollständige Typen vervollständigen.