void zeiger



  • Hiho Leute,
    wieder mal eine Frage 😛

    wenn ich einen void zeiger definiere und ihn auf eine int Variable zeigen lasse...

    int i=7;
    void* vp=&i;
    

    ... und den void zeiger dann dereferenzieren möchte ...

    cout << *vp; // entspricht *( (void*)vp )
    

    ... kommt eine Fehlermeldung --> `void*' is not a pointer-to-object type.

    Diese Fehlermeldung kann ich mir noch erklären,
    denn sizeof(void) funktioniert nicht, woraus ich schließe, dass void keine Größe hat und man somit auch nicht dereferenzieren kann, weil die Größe des Datenobjektes dem void Zeiger nicht bekannt ist.

    Ist dies korrekt, wie ich es hergeleitet habe?

    Somit müsste ich also folgendes machen...

    cout << *( (int*)vp );
    

    ... das auch einwandfrei funktioniert 🙂

    Nun viel mir aber folgendes auf.
    Wenn ich folgendes mache...

    cout << *( (void**)vp )
    

    ... funktioniert es auf einmal (in hex Ausgabe). Wieso funktioniert es plötzlich, wenn ich den Dereferenzierungs-Operator doppelt anwende?

    Dies kann ich mir vor allem darum nicht erklären, weil wenn ich...

    cout << (void*)vp;
    cout << (void**)vp;
    

    ... 2x das genau Gleiche ausgeben wird.

    Ich habe schon im Internet nach Erklärung gesucht, bin aber nicht fündig geworden. Hoff ihr könnt mir erklären,
    was genau passiert wenn ich den Dereferenzierungs-Operator doppelt anwende.

    MFG Dweb



  • sizeof( void* ) hat eine Groesse.

    cout << (void*)vp << " " << (void**)vp << endl;
    

    Funktioniert, weil du zweimal einen Zeiger ausgibts. Der Inhalt des Zeigers wird ausgegeben. Da ist kein Dereferenzierungsoperator. Und: Du solltest dir nicht aus den ausprobierten Sachen etwas herleiten, sondern ein Buch lesen.


  • Administrator

    void Übersetzung

    Ein void-Zeiger ist ein Zeiger auf eine Speicheradresse und mehr nicht. Dieser Zeiger hat keine Typinformationen und da der Typ nicht bekannt ist, kann man diesen Zeiger auch nicht dereferenzieren. Also hast du da zum Teil richtig argumentiert.

    Nun zu deinen Versuchen:
    1.

    cout << *( (int*)vp );
    

    Das ist ein C-Cast von einem void-Zeiger zu einem int-Zeiger, danach wird der int-Zeiger dereferenziert. In C++ würde man hier eher den C++ Cast nehmen:

    cout << *static_cast<int*>(vp);
    

    Wieso es funktioniert ist wohl klar. Man sagt dem Kompiler einfach, dass der void-Zeiger eigentlich ein int-Zeiger ist. Also dass an dieser Adresse im Speicher ein int liegt.

    cout << *( (void**)vp )
    

    Hier machst du keine doppelte Dereferenzierung, sondern du machst einen C-Cast des void-Zeigers in einen Zeiger auf einen void-Zeiger. Danach wird das ganze derefernziert, wodurch ein void-Zeiger herauskommt, welcher in hexadezimaler Darstellung angezeigt wird.

    Also kurz anders dargestellt:

    void** vpp = static_cast<void**>(vp);
    void* vp2 = *vpp;
    cout << vp2;
    

    Das ist nicht nur ziemlich unsinnig, sondern auch noch gefährlich. Wenn dein ursprünglicher int nicht die gleiche Grösse wie dein void-Zeiger hätte, dann könnte das zu undefiniertem Verhalten führen. Nicht wirklich zu empfehlen.

    Vielleicht noch ein Zusatz, wieso die Derferenzierung hier funktionert. Ein void-Zeiger hat eine Grösse, ist nämlich 4 oder 8 Byte gross, je nachdem wieviele Bytes für eine Adresse benötigt werden. Also ein sizeof(void*) liefert einen Wert zurück.

    cout << (void*)vp;
    cout << (void**)vp;
    

    Das erste ist ziemlicher Unsinn. Du machst einen C-Cast von einem void-Zeiger auf einen void-Zeiger.
    Das zweite hatten wir schon, ein C-Cast von einem void-Zeiger auf einen Zeiger auf einen void-Zeiger 🙂
    Klar bleibt die Ausgabe die Selbe. Du machst ja nur ein Cast, so dass der Zeiger anders interpretiert wird, der Wert des Zeigers bleibt aber gleich. Eine Dereferenzierung findet hier nicht statt.

    Grüssli



  • sizeof(void) funktioniert nicht, woraus ich schließe, dass void keine Größe hat und man somit auch nicht dereferenzieren kann

    void ist ein C/C++ Schlüsselwort und hat keine Größe, da void einen nicht existierenden Wert bezeichnet. Da kein Wert existiert muss sizeof(void) eine Fehlermledung liefern.

    Dagegen liefert *sizeof(void ) die Größe des generischem void-Zeigers in den jeder andere Zeiger auf ein Objekt konvertiert werden kann.

    Wenn ich folgendes mache...

    cout << *( (void**)vp )
    

    ... funktioniert es auf einmal (in hex Ausgabe). Wieso funktioniert es plötzlich, wenn ich den Dereferenzierungs-Operator doppelt anwende?

    Es sieht nur so aus als ob es funktionieren würde. Dein Beispiel ist mit einem Integer Wert gerechnet der zufällig dieselbe Länge hat wie der void* Zeiger, nähmlich 4 Byte. Wenn Du einen anderen Datentypen verwendest klappt das Beispiel nicht mehr.

    void *vp;
    char *zz="aaaaaaaaaaaa";
    vp = zz;
    cout << *(void**)vp;     //Gibt nur 4x 'a'(HEX 61) aus statt 12x
    

    Warum dieses Ergebniss?
    [] vp ist ein void Zeiger
    [
    ] zz ist ein Zeiger auf eine Zeichenkette (zz)
    [] vp=zz vp ist jetzt ein Zeiger auf die Zeichenkette zz
    [
    ] (void**)vp verwandelt den void-Zeiger in einen void-"Zeiger auf einen Zeiger", der auf die Adresse des ersten Elements des Zeichenkettenfeldes zz zeigt.
    [*] *(void **)Liefert den Inhalt des Zeichekettenfeldes in der Breite des void-Zeigers, in unserem Beispiel vier Bytes

    Wäre der void Zeiger 8 Byte breit würden die ersten acht Byte ausgegeben.

    void kann auch nur Zeiger oder Zeiger auf Zeiger casten. Würdest du zum Beispiel das folgende schreiben

    void *vp;
    char *zz="aaaaaaaaaaaa";
    vp = zz;
    cout << *(void***************)vp;     //Gibt ebenfalls nur 4x 'a' aus
    

    wäre das Ergebnis gleich 🙂



  • eure Antworten haben weitergeholfen. dankö 🙂


Anmelden zum Antworten