Dereferenzierung einer float-Variablen mit einem void-Zeiger:
%Vor% Ausgabe: 7.500000
Dereferenzierung einer Variablen mithilfe eines ganzzahligen Zeigers:
%Vor% Ausgabe: 7.500000
In beiden sind die Ausgänge gleich. Was ist der Grund für die Dereferenzierung verschiedener Datentypvariable, wenn wir einen normalen Zeiger typisieren können?
Ein void
-Zeiger ist ein generischer Zeiger , der die Adresse eines beliebigen Typs enthalten kann und typecast zu jedem Typ.
Im ersten Fall wurde das Programm erfolgreich kompiliert und ohne Warnung oder Fehler ausgeführt, da die Verwendung eines void
Zeigers zum Konvertieren von einem Zeigertyp in einen anderen und Speichern oder Umwandeln in den endgültigen Typ sicher ist, ohne Daten zu verlieren .
Aber im zweiten Fall hat der GCC Compiler eine Warnung generiert
%Vor%Sprachcompiler:
%Vor%Der C11-Standard, 6.3.2.3, Absatz 7:
Ein Zeiger auf ein Objekt oder einen unvollständigen Typ kann in a konvertiert werden Zeiger auf ein anderes Objekt oder unvollständiger Typ . Wenn das Ergebnis Zeiger ist nicht korrekt für den referenzierten Typ, das Verhalten ausgerichtet ist undefiniert .
Das Konvertieren eines Datenzeigers in void*
Zeiger und zurück gibt garantiert den ursprünglichen Zeiger zurück.
Ab C11 Standardentwurf N1570:
6.3.2.3 Zeiger
- Ein Zeiger auf
void
kann in oder von einem Zeiger auf einen beliebigen Objekttyp konvertiert werden. Ein Zeiger auf jeder Objekttyp kann in einen Zeiger auf void und zurück konvertiert werden; das Ergebnis soll Vergleiche mit dem ursprünglichen Zeiger.
Konvertieren von Datenzeiger zu einem anderen Datenzeiger als void*
( int*
in Ihrem Beispiel) kann funktionieren. Es hängt vom verwendeten Compiler und dem System ab, auf dem Sie sich befinden. Nicht alle Systeme verwenden möglicherweise dieselbe interne Repräsentation für unterschiedliche Zeigertypen.
- Ein Zeiger auf einen Objekttyp kann in einen Zeiger auf einen anderen Objekttyp umgewandelt werden. Wenn die resulting pointer ist nicht richtig ausgerichtet 68 für den referenzierten Typ ist das Verhalten nicht definiert. Andernfalls wird das Ergebnis, wenn es wieder zurückverwandelt wird, gleich dem Wert von Original-Zeiger. Wenn ein Zeiger auf ein Objekt in einen Zeiger auf einen Zeichentyp konvertiert wird, Das Ergebnis zeigt auf das niedrigste adressierte Byte des Objekts. Aufeinander folgende Inkremente des Ergebnis, bis zur Größe des Objekts, Zeiger auf die verbleibenden Bytes des Objekts.
Dies unterscheidet sich von strengen Aliasregeln .
%Vor%Der obige Code bricht die strikte Alias-Regel, da der dereferenzierte Typ nicht mit dem ursprünglichen Typ übereinstimmt. Dies führt zu undefiniertem Verhalten und ist immer ungültiger Code.
Ein void
-Zeiger ist (irgendwie) untypisiert. Es kann auf alles zeigen, ohne dass sich der Compiler beschweren muss. z.B. Wenn Sie eine int
Variable haben, können Sie sicher einen void
Zeiger erstellen, der darauf zeigt und ihn weitergibt. z.B.
ist in Ordnung, aber
%Vor%wird den Compiler stören
Dies ist besonders nützlich für Funktionen, die mit mehreren Zeigertypen arbeiten oder wenn Sie entscheiden, was zur Laufzeit ist.
void-Zeiger können jedoch nicht direkt dereferenziert werden ( *
), da der Compiler seinen Typ nicht kennt. Also,
bricht ab, wenn p ein ungültiger Zeiger ist. Wir müssen die Größe dessen wissen, worauf es hinweist, um es zu dereferenzieren, und dies geschieht mit einer manuellen Typumwandlung (wie Sie es getan haben).
In Ihrem speziellen Fall haben Sie einen Zeiger, der auf einen Float zeigt, den Sie vor dem Drucken in Float einschreiben. So erhalten Sie die gleiche Ausgabe. Der Zeiger void *
spielt hier nicht wirklich eine große Rolle.
Ein Beispiel dafür, wo Sie eine void *
benötigen, ist die Funktion malloc
. Wenn Sie sich den Prototyp ansehen, wird eine void *
zurückgegeben. ein Block aus Rohspeicher. Sie müssen dies als konkreten Typ eingeben, bevor Sie Zeigerarithmetik und Dereferenzierung durchführen können.
Tags und Links c type-conversion types void-pointers