Der sizeof Operator liefert falsche Grösse?



  • @Registrierter Troll
    Du machst mir Angst...
    Auf deine Aussage habe ich leider keine Antwort, ich bin immer davon ausgegangen, dass jedes Byte im Speicher adressiert werden kann. Unabhängig von der Architektur. Bei 32bit kann ich ja IMHO ca. 4GB speicher addressieren. Eine Konsequenz deiner Aussage währe ja doch dann, dass ich ca. 16BG adressieren könnte, aber halt nur jedes 4te Byte?



  • @Janjan
    Viele Tutorials und Bücher, die ich gelesen habe und die Verarbeitung von Binärdaten behandeln, lesen und schreiben direkt in und aus Strukturen aus oder in Dateien...

    Daher bin ich ehrlich gesagt gerade ein wenig schockiert... 😮



  • Ishildur schrieb:

    @Registrierter Troll
    Du machst mir Angst...
    Auf deine Aussage habe ich leider keine Antwort, ich bin immer davon ausgegangen, dass jedes Byte im Speicher adressiert werden kann. Unabhängig von der Architektur. Bei 32bit kann ich ja IMHO ca. 4GB speicher addressieren. Eine Konsequenz deiner Aussage währe ja doch dann, dass ich ca. 16BG adressieren könnte, aber halt nur jedes 4te Byte?

    Das ist unsinn. Mag sein, dass eine Architektur nur an jedem 4ten Byte zugreifen kann, aber die Implementierung deines C++ Codes muss dies berücksichtigen. Dann muss eben der geschriebene Maschinencode zur Not 3 byte früher lesen, und die ersten 3 Byte wegwerfen. Darauf musst du dank Standard in deinem Code nicht achten, darauf muss der Compiler für dich achten. 😉



  • Ishildur schrieb:

    @Janjan
    Viele Tutorials und Bücher, die ich gelesen habe und die Verarbeitung von Binärdaten behandeln, lesen und schreiben direkt in und aus Strukturen aus oder in Dateien...

    Daher bin ich ehrlich gesagt gerade ein wenig schockiert... 😮

    Die machen es schlichtweg falsch. Es gibt leider sehr sehr sehr viele schlechte Tutorials und Bücher...



  • @Janjan
    Puuhhhh.... Dank dir kann ich wieder ruhig schlafen 😃



  • Ishildur schrieb:

    Auf deine Aussage habe ich leider keine Antwort, ich bin immer davon ausgegangen, dass jedes Byte im Speicher adressiert werden kann. Unabhängig von der Architektur.

    Kann es ja auch, aber garantiert funktionieren tut das nur, wenn du wirklich nur byteweise zugreifst.

    Bei 32bit kann ich ja IMHO ca. 4GB speicher addressieren. Eine Konsequenz deiner Aussage währe ja doch dann, dass ich ca. 16BG adressieren könnte, aber halt nur jedes 4te Byte?

    Nein. Die Konsequenz ist, dass ein 32-Bit-Wert nur dann in einem 32-Bit-Zugriff gelesen werden kann, wenn er an durch 4 teilbaren Adressen liegt. Der Adressraum bleibt gleich groß.

    Viele Tutorials und Bücher, die ich gelesen habe und die Verarbeitung von Binärdaten behandeln, lesen und schreiben direkt in und aus Strukturen aus oder in Dateien...

    In vielen Tutorials und Büchern steht halt Müll drin. 🙂



  • Janjan schrieb:

    Darauf musst du dank Standard in deinem Code nicht achten, darauf muss der Compiler für dich achten. 😉

    reinterpret_cast heißt aber auch "ich weiß was ich hier tue, lass mich mal machen".

    Ishildur schrieb:

    @Janjan
    Puuhhhh.... Dank dir kann ich wieder ruhig schlafen 😃

    Nur weil er sagt was du hören willst, hat er noch lange nicht recht. 🙂



  • @Registrierter Troll
    Ok, kannst du mir ein Codebeispiel geben, wie ich folgende Daten "korrekt" auslese:
    Ich habe einen Zeiger auf eine Speicheradresse, welche folgende Daten enthält:
    1Byte,2Byte,8Byte,1Byte,4Byte,2Byte
    Diese muss ich nun in eine Struktur abfüllen oder auf den Bildschirm oder was weis ich. Die Grösse des Zeigers darfst du selber wählen...



  • Registrierter Troll schrieb:

    Janjan schrieb:

    Darauf musst du dank Standard in deinem Code nicht achten, darauf muss der Compiler für dich achten. 😉

    reinterpret_cast heißt aber auch "ich weiß was ich hier tue, lass mich mal machen".

    ZeigerTyp *zeiger = ...;
    reinterpret_cast<int*>(zeiger);
    

    Das heißt, ich weiß was ich mache, ich weiß dort liegen _int_ Daten für mich, also mecker nicht.



  • @Registrierter Troll

    Dieser Code wäre dann aber IMHO nach deiner Aussage auch "gefährlich" ?

    uint32* p32 = new uint32[512];
    uint8*  p8 = reinterpret_cast<uint8*>(p32);
    uint8  val  = p8[3];
    

    Denn dieser Code kopiert nun das dritte Oktett des ersten Integers in Val, das ja nun sicher nicht mehr 32bit aligned ist...



  • Ishildur schrieb:

    Ok, kannst du mir ein Codebeispiel geben, wie ich folgende Daten "korrekt" auslese:

    Das wirklich richtig zu machen ist nicht mit ein paar Zeilen getan, und da ich mir nicht hundertprozentig sicher bin ob ich in diesem Fall wirklich recht habe, lasse ich das lieber mal. Es würde vermutlich auf etwas hinauslaufen, was ähnlich der zweiten Antwort (I have to disagree with many of the responses here...) auf eine ähnliche Frage bei Stack Overflow ist.

    Du kannst ja mal selbst im Standard die Abschnitte 3.10.15 und 5.2.10 durchlesen und mit all ihren Implikationen verstehen, dann siehst du warum das nicht so einfach ist.

    Denn dieser Code kopiert nun das dritte Oktett des ersten Integers in Val, das ja nun sicher nicht mehr 32bit aligned ist...

    Es spielt keine Rolle, wie der Speicher angelegt wurde. Der Zugriff ist entscheidend. Ausgehend von der Annahme, dass uint8 ein [unsigned] char ist und geringere Anforderungen an das Alignment stellt, ist der Zugriff in Ordnung:

    3.10.15 schrieb:

    15 If a program attempts to access the stored value of an object through an lvalue of other than one of the fol-
    lowing types the behavior is undefined:
    — the dynamic type of the object,
    — a cv-qualified version of the dynamic type of the object,
    — a type that is the signed or unsigned type corresponding to the dynamic type of the object,
    — a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of
    the object,
    — an aggregate or union type that includes one of the aforementioned types among its members (includ-
    ing, recursively, a member of a subaggregate or contained union),
    — a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
    — a char or unsigned char type.

    Janjan schrieb:

    ZeigerTyp *zeiger = ...;
    reinterpret_cast<int*>(zeiger);
    

    Das heißt, ich weiß was ich mache, ich weiß dort liegen _int_ Daten für mich, also mecker nicht.

    Wenn du dir die entsprechenden Stellen im Standard durchliest, wirst du sehen dass es so einfach nicht ist.


Anmelden zum Antworten