Dereferenzieren des Zeigers auf einen unvollständigen Typfehler in C

Jay Shaw 12 Oktober 2023
  1. Ursachen des Fehlers Dereferenzierung des Zeigers auf unvollständigen Typ in C
  2. Unvollständige Typen in C
  3. Referenzieren und Dereferenzieren eines Zeigers in C
  4. Lösen Sie den Fehler Dereferenzierungszeiger auf unvollständigen Typ in C
  5. Abschluss
Dereferenzieren des Zeigers auf einen unvollständigen Typfehler in C

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.

  1. Was sind unvollständige Typen?
  2. 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:

  1. Ein Strukturtyp ohne Mitglieder.
  2. Ein Gewerkschaftstyp ohne Mitglieder.
  3. 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.

Verwandter Artikel - C Error