Frage zur Pointerkonvertierung / Pointerarithmetik



  • Guten Tag!

    Ich habe hier eine C-Bibliothek, die ich in einem C++-Projekt verwenden will. Jetzt habe ich 6 Fehler, die ein kompilieren verhindern. Hier der Code:

    void *vsector;  // Irgendwo am Anfang der Funktion 
            [...]
    
    	vsector+=8;  // So wie ich das verstanden habe in C erlaubt, in C++ nicht
    
    	// low word	von cluster (20,2)
    	*(uint16_t*)vsector=(cluster&0xffff0000)>>16;
    	vsector+=6;
    
    	// high word von cluster (26,2)
    	*(uint16_t*)vsector=(cluster&0x0000ffff);
    	vsector+=2;
    
    	// laenge (28,4)
    	*(uint32_t*)vsector=length;
    

    Sind meine Modifikationen korrekt?

    uint8_t *vsector; // Wurde nachfolgend als uint8 behandelt, daher der Typ
           [...]
           vsector+=8;
    
           // CHANGE:
           uint16_t* vsector_16 = (uint16_t*)vsector;
    
    	// low word	von cluster (20,2)
    	*vsector_16=(cluster&0xffff0000)>>16;
    	vsector_16+=6;
    
    	// high word von cluster (26,2)
    	*vsector_16=(cluster&0x0000ffff);
    	vsector_16+=2;
    
    	// laenge (28,4)
    	*(uint32_t*)vsector_16=length;
    

    Über eure Hilfe freue ich mich 🙂



  • welche

    HelfendeHand schrieb:

    Guten Tag!

    Ich habe hier eine C-Bibliothek, die ich in einem C++-Projekt verwenden will. Jetzt habe ich 6 Fehler, die ein kompilieren verhindern.

    wie waere es wenn du uns verraetst welche fehlermeldungen du bekommst und in welchen zeilen ?



  • Meep Meep schrieb:

    welche

    HelfendeHand schrieb:

    Guten Tag!

    Ich habe hier eine C-Bibliothek, die ich in einem C++-Projekt verwenden will. Jetzt habe ich 6 Fehler, die ein kompilieren verhindern.

    wie waere es wenn du uns verraetst welche fehlermeldungen du bekommst und in welchen zeilen ?

    Oh klar:

    Überall dort, wo der void-Pointer inkrementiert wird, gibt/gab es einen Fehler:

    expression must be a pointer to a complete object type

    Weil das wohl nur in C geht, nicht in C++



  • Grundsätzlich mal (zu deinem gewählten Beitragstitel):
    Reine Zeiger-Casts in C ("Zeigerkonvertierung") ist immer sehr fraglich, lässt meistens auf fehlerhaftes Design schließen, bei Anfängern immer auf Unkenntnis.
    C trotz des relativ kleinen Sprachumfanges Nichts für Anfänger.
    Es sind viele implizite Abhängigkeiten zu beachten, C ist von Praktikern für Praktiker entwickelt worden, nicht für Schüler.

    HelfendeHand schrieb:

    void *vsector;  // Irgendwo am Anfang der Funktion 
            [...]
    
    	vsector+=8;  // So wie ich das verstanden habe in C erlaubt, in C++ nicht
    
    uint8_t *vsector; // Wurde nachfolgend als uint8 behandelt, daher der Typ
           [...]
           vsector+=8;
    

    Warum hast du es denn geändert, wenn es "erlaubt" wäre?
    Deine o.g. Vermutung ist falsch.
    Man kann (standardkonform) keinen void-Zeiger inkrementieren. Woher soll der Compiler denn wissen, um wieviele Bytes er die Speicheradresse hochzählen soll?
    Du hast Zeiger nicht verstanden, etwas ganz Essentielles in C und dein Problem hier ist C und nicht C++.

    uint8_t *vsector; /* Zeiger hat einen gültigen Typ, d.h. es kann fleißig de/inkrementiert werden */
           [...]
           vsector = Ausgangsadresse;           
    
        // low word    von cluster (20,2)
        vsector += 20;  /* "Hochzählen" der Adresse um 20*sizeof(uint8_t), d.h. 20*8 Bit */
        *(uint16_t*)vsector = (cluster&0xffff0000)>>16; /* hier werden sizeof(uint16_t) == 16 Bit zugewiesen */
    
        // high word von cluster (26,2)
        vsector += 6;  /* "Hochzählen" der Adresse um 6*sizeof(uint8_t), d.h. 6*8 Bit */
        *(uint16_t*)vsector = (cluster&0x0000ffff); /* hier werden sizeof(uint16_t) == 16 Bit zugewiesen */
    
        // laenge (28,4)
        vsector += 2;  /* "Hochzählen" der Adresse um 2*sizeof(uint8_t), d.h. 2*8 Bit */
        *(uint32_t*)vsector=length; /* hier werden sizeof(uint32_t) == 32 Bit zugewiesen */
    

    Bei solchen Multibyte-Rumfrickeleien musst du natürlich noch die aktuelle Bytereihenfolge deines Systems beachten, wenn du mit Daten arbeitest, die von außerhalb deines Prozesses kommen (Dateien, Netzwerk, Shared Memory, ...)



  • Wutz schrieb:

    HelfendeHand schrieb:

    void *vsector;  // Irgendwo am Anfang der Funktion 
            [...]
    
    	vsector+=8;  // So wie ich das verstanden habe in C erlaubt, in C++ nicht
    
    uint8_t *vsector; // Wurde nachfolgend als uint8 behandelt, daher der Typ
           [...]
           vsector+=8;
    

    Warum hast du es denn geändert, wenn es "erlaubt" wäre?
    Deine o.g. Vermutung ist falsch.
    Man kann (standardkonform) keinen void-Zeiger inkrementieren.

    Also irgendwie fühle ich mich gänzlich missverstanden. War mein Post so scheisse? Ich habe das ganze angepasst, weil die Bibliothek in C ist, ich aber in C++ entwickle. Und siehe stackoverflow:

    http://stackoverflow.com/questions/3523145/pointer-arithmetic-for-void-pointer-in-c

    Void-Pointer-Arithmetik soll, wenn ich das aus diesem Thema richtig verstanden habe, in C gehen. Aber AUSSCHLIESSLICH in C. Ich entwickle aber in C++! Deswegen MUSS ich diese Lib anpassen. Ich weiß, was Pointer sind.

    Meine Frage ist nur, ob meine Anpassung korrekt ist.



  • HelfendeHand schrieb:

    Und siehe stackoverflow:

    http://stackoverflow.com/questions/3523145/pointer-arithmetic-for-void-pointer-in-c

    Void-Pointer-Arithmetik soll, wenn ich das aus diesem Thema richtig verstanden habe, in C gehen. Aber AUSSCHLIESSLICH in C. Ich entwickle aber in C++! Deswegen MUSS ich diese Lib anpassen. Ich weiß, was Pointer sind.

    Dann musst du aber auch einen C-Compiler benutzen. Ob dein C++ Zeugs dann noch funktioniert, ist die nächste Frage...



  • HelfendeHand schrieb:

    Sind meine Modifikationen korrekt?

    Nein. vsector_16+=6; bewegt den Zeiger um 6 uint16_t, d.h. 12 Bytes.


  • Mod

    Man kann übrigens relativ problemlos einen Teil eines Programms mit einem C-Compiler übersetzen, den anderen mit einem C++-Compiler und das ganz dann vom Linker zu einem einzigen Programm zusammenbauen lassen.


  • Mod

    HelfendeHand schrieb:

    Und siehe stackoverflow:

    http://stackoverflow.com/questions/3523145/pointer-arithmetic-for-void-pointer-in-c

    Void-Pointer-Arithmetik soll, wenn ich das aus diesem Thema richtig verstanden habe, in C gehen.

    Das hast du falsch verstanden, und etwas anderes geht auch aus dem Link nicht hervor.

    C99 schrieb:

    6.5.6/2
    For addition, either both operands shall have arithmetic type, or one operand shall be a
    pointer to an object type and the other shall have integer type. (Incrementing is
    equivalent to adding 1.)

    C99 schrieb:

    6.2.5 Types
    1 The meaning of a value stored in an object or returned by a function is determined by the
    type of the expression used to access it. (An identifier declared to be an object is the
    simplest such expression; the type is specified in the declaration of the identifier.) Types
    are partitioned into object types (types that fully describe objects), function types (types
    that describe functions), and incomplete types (types that describe objects but lack
    information needed to determine their sizes).
    [...]
    19 The void type comprises an empty set of values; it is an incomplete type that cannot be
    completed.

    void* ist zwar ein object pointer type; void selbst aber kein object type und somit void* kein pointer to an object type.

    (object pointer type kommt im C-Standard nur in einer Fußnote vor und wird dort nicht formal definiert). In C++ existiert eine formale Definition (3.9.2/2) in genau diesem Sinne.



  • Athar schrieb:

    HelfendeHand schrieb:

    Sind meine Modifikationen korrekt?

    Nein. vsector_16+=6; bewegt den Zeiger um 6 uint16_t, d.h. 12 Bytes.

    Ich hab das jetzt nochmal in Ruhe nachvollzogen anhand eines separaten Miniprogramms. Ja, ist richtig, das ist nicht korrekt.

    SeppJ schrieb:

    Man kann übrigens relativ problemlos einen Teil eines Programms mit einem C-Compiler übersetzen, den anderen mit einem C++-Compiler und das ganz dann vom Linker zu einem einzigen Programm zusammenbauen lassen.

    Danke für den Denkanstoß. Die Idee gefällt mir eigentlich ganz gut. Und danke auch an Camper. Void kann also nicht inkr/dekr werden. Wäre interessant, was der Ersteller der Bibliothek für einen Compiler hatte



  • Caste ihn einfach nach std::uintptr_t .


Anmelden zum Antworten