Integer in 4 Bytes zerlegen - Wie?
-
Nexus schrieb:
Kann das nicht nur zu undefiniertem Verhalten führen, weil folgende Bedingung nicht garantiert ist?
sizeof(int) == 4 * sizeof(char)
Das Problem hat man bei Bitschiebereien nämlich auch.
Deshalb würde man dann ja auch int32_t verwenden
-
Das heisst, das undefinierte Verhalten aufgrund von Lesen von anderen
union
-Membern als der geschriebenen bestünde weiterhin?
-
ich denke mal, das undefinierte Verhalten rührt daher, dass Union nicht garantieren kann, dass alle Member gleich groß sind.
Speichert man einen Wert in einen char und holt in sich über ein int wieder raus, dann braucht man sich nicht zu wundern, dass ein anderer Wert drinsteht. Andersrum ist es ja noch schlimmer
Oder was rechtfertig das undefinierte Verhalten?
-
Es ist ein rein theoretisches Problem.
In der Praxis funktioniert die Union Methode.
-
Bei der Methode mit der Union kommt ins Spiel, wie hat die Maschine den int32_t abgespeichert?
littel endian oder big endian?
Deshalb ist die Methode:
David_pb schrieb:
So:
int a = value & 0xff; int b = ( value >> 8 ) & 0xff; int c = ( value >> 16 ) & 0xff;
...
allgemeingültiger und besser.
-
Wilma schrieb:
Bei der Methode mit der Union kommt ins Spiel, wie hat die Maschine den int32_t abgespeichert?
littel endian oder big endian?
Deshalb ist die Methode:
David_pb schrieb:
So:
int a = value & 0xff; int b = ( value >> 8 ) & 0xff; int c = ( value >> 16 ) & 0xff;
...
allgemeingültiger und besser.
Wieso?
-
Ein int32_t hat immer die Bits 0 bis 31 - ob littel oder big endian gespeichert, spielt beim Schieben keine Rolle.
-
Wilma schrieb:
Ein int32_t hat immer die Bits 0 bis 31 - ob littel oder big endian gespeichert, spielt beim Schieben keine Rolle.
Und int32_t hat auch immer die Bytes 0-3
egal ob little big oder median gespeichert...
-
Und warum nicht "long" anstatt "int32_t"?
-
Frage1 schrieb:
Und warum nicht "long" anstatt "int32_t"?
weil du einen 4 byte breiten typen haben willst und long wenn du pech hast 7,3 milliarden bytes groß ist?
-
So ne Kacke aber auch, ich dachte "long" ist immer 4 Bytes lang, garantiert das der Standard nicht?
-
Nein, siehe dazu auch diesen Thread.
-
Shade Of Mine schrieb:
Wilma schrieb:
Ein int32_t hat immer die Bits 0 bis 31 - ob littel oder big endian gespeichert, spielt beim Schieben keine Rolle.
Und int32_t hat auch immer die Bytes 0-3
egal ob little big oder median gespeichert...Ich verstehe weder die "Warum?"-Frage ein paar Posts vorher noch diese Aussage.
Little Endian: LSB 2B 3B HSB
Mapt man das direkt auf Bytes, dann bekommt man für byte[0] eben das LSB
Big Endian: HSB 3B 2B LSB
Mapt man das direkt auf Bytes, dann bekommt man für byte[0] eben das HSB(uint32_t >> 24) && 0xFF
liefert hingegen immer das HSB. Egal, ob dem Wert Little- oder Big Endian zugrunde liegt.
-
Danke, interessanter Thread @Nexus.
Eine Frage aber noch:
"int32_t" ist auf einem 32bit System gleich "int" oder "long" nehme ich an.
Und auf einem 64bit System? short? Ist "short" auf einem 64bit system 32bit breit?
-
Kapier ich nicht. Kannst du mir das bitte mal vorrechnen?
Irgendwie sehe ich den Unterschied nicht...
-
Shade Of Mine schrieb:
Kapier ich nicht. Kannst du mir das bitte mal vorrechnen?
Irgendwie sehe ich den Unterschied nicht...Ich hoffe, Du beziehst Dich auf meinen Post...
Beispiel:
uint32_t val = 0xAABBCCDD
Auf einer Big Endian Maschine wäre das dann im Speicher
AA BB CC DD
Auf einer LittleEndian MaschineDD CC BB AA
Macht man jeweils auf einer Little Endian Maschine (potentielle Probleme neben der Endianess mal außer acht gelassen) nun Folgendes:
Big Endian:uint8* pval = &val; ausgabe(pval[0]); // ->AA
Little Endian:
uint8* pval = &val; ausgabe(pval[0]); // -> DD
hat man unterschiedliche Ergebnisse. Das ist klar denke ich.
val & 0xFF
liefert hingegen immer DD. Egal ob Little- oder Big Endian.
Soll heißen: Mit der Bitshift Methode lässt sich ein int plattformunabhängig serialisieren. Irgendwelche Overlays sind hingegen (logischerweise) "Implementation dependent". Und die Sache mit der Union ist so ein Overlay.
-
Tachyon schrieb:
val & 0xFF
liefert hingegen immer DD. Egal ob Little- oder Big Endian.
Soll heißen: Mit der Bitshift Methode lässt sich ein int plattformunabhängig serialisieren. Irgendwelche Overlays sind hingegen (logischerweise) "Implementation dependent". Und die Sache mit der Union ist so ein Overlay.Nur was wenn ich val vorher 24bits nach rechts schiebe?
Wenn ich AA BB CC DD um 24 bit nach rechts verschiebe habe ich ja
00 00 00 AAWenn ich aber DD CC BB AA um 24bit nach rechts verschiebe habe ich
00 00 00 DDwenn ich
val & 0xFF mache, dann weiss ich ja dennoch nicht in welchem byte nun der interessante wert steht...
-
Ich vermute, daß der Shift - Operator >> eben nicht 'nach rechts' verschiebt, sondern 'in Richtung LSB', rein physikalisch also auf einem Little Endian System anders, als auf einem Big Endian System.
-
Belli schrieb:
Ich vermute, daß der Shift - Operator >> eben nicht 'nach rechts' verschiebt, sondern 'in Richtung LSB', rein physikalisch also auf einem Little Endian System anders, als auf einem Big Endian System.
macht natürlich sinn. danke.
-
Shade Of Mine schrieb:
Nur was wenn ich val vorher 24bits nach rechts schiebe?
Wenn ich AA BB CC DD um 24 bit nach rechts verschiebe habe ich ja
00 00 00 AAWenn ich aber DD CC BB AA um 24bit nach rechts verschiebe habe ich
00 00 00 DDwenn ich
val & 0xFF mache, dann weiss ich ja dennoch nicht in welchem byte nun der interessante wert steht...val = 0xAABBCCDD; val >>= 24; // val == 0xAA