Word aus 2 Bytes basteln
-
m00ni schrieb:
die Bytes haben Big Endian format und das Word soll eben nach der Umwandlung auch Big Endian sein.
Bytes selbst haben kein Endian, nur eine Reihung dieser.
Da du Bigendian brauchst, kannst du den Unix-Standard POSIX benutzen, z.B.#include <arpa/inet.h> /* unter win auch winsock2.h */ unsigned short bigend_word(unsigned char hi,unsigned char lo) { return htons(hi<<8|lo); }
htons kümmert sich dann um den Rest.
-
mgaeckler schrieb:
supertux schrieb:
so?
...(((LZSWORD) b_low_i) >> 8)... }
Was passiert, wenn ich ein Byte um 8 Bit nach rechts shifte?
eigentlich solltest du dann 0 bekommen, deshalb habe ich es explizit auf einen Datentype gecastet, der mehr Bits enthält.
m00ni schrieb:
Hab mir das ganze jetzt nochmal angekuckt und wenn ich das nicht falsch verstehe ist Big Endian doch so aufgebaut:
0....8....16
Das heißt ich muss doch die least significant bits reinpacken und nach links verschieben dann einfach die oberen mit rein odern.
LZSWORD w_retValue = b_low_i << 8 | b_high_i;
Oder etwa nicht?
ja, siehe meinen letzten Post. Wobei, wenn b_low_i nur 8-Bit breit ist, dann ist b_low_i << 8 sehr wahrscheinlich 0.
-
Ich haette 'nen
union
genommen.
-
knivil schrieb:
Ich haette 'nen
union
genommen.Strenggenommen aber undefiniertes Verhalten. Natürlich wird jede reale Implementierung das machen, was du hier erwartest, aber warum ohne Not Undefiniertes tun?
-
supertux schrieb:
mgaeckler schrieb:
supertux schrieb:
so?
...(((LZSWORD) b_low_i) >> 8)... }
Was passiert, wenn ich ein Byte um 8 Bit nach rechts shifte?
eigentlich solltest du dann 0 bekommen, deshalb habe ich es explizit auf einen Datentype gecastet, der mehr Bits enthält.
Wenn ich jetzt Dein Informatiklehrer wäre, würde ich sagen "Setzen 6". Bin ich aber nicht.
1. Die Lösung mit 0 stimmt nur dann, wenn Du ein vorzeichenloses Byte hast. Bei einem vorzeichen behafteten Byte wird einfach das Vorzeichen nachgeschoben:-127 >> 8 = -1
2. Meinst Du im Ernst, daß Dein cast aus Deinem 8 Bitwert einen 16 Bitwert zaubert? Pass auf: das passiert:
10101010 gecastet wird zu 0000000010101010. So und jetzt stell Dir vor, das wird um 8 Bits nach rechts verschoben. Was haben wir dann?0000000000000000
Dein cast hat also nichts, rein gar nichts gebracht. Bitte beachte, das Beispiel so gilt nur für vorzeichenlose Bytes.
supertux schrieb:
a, siehe meinen letzten Post. Wobei, wenn b_low_i nur 8-Bit breit ist, dann ist b_low_i << 8 sehr wahrscheinlich 0.
Tut mir leid, schon wieder daneben. b_low_i wird automatisch zu einem int bzw. unsigned int gecastet. Es stehen damit 16 oder mehr Bits zur Verfügung und b_low_i << 8 wird daher dann und nur dann 0 wenn b_low_i schon 0 ist.
mfg Martin
-
knivil schrieb:
Ich haette 'nen
union
genommen.meinst Du sowas?
union xyz { unsigned short word; struct { unsigned char byte1, byte2; } endian; };
Das ist nicht ungefährlich. Der Standard garantiert Dir nur, daß alle Datenfelder in einem struct in genau der Reihenfolge im Speicher erscheinen, wie sie auch in der Deklaration erscheinen. Der Compiler darf aber z.B. zwischen den Elementen beliebige Füllbytes einfügen.
Der Union bringt Dir keinen nennenswerten Vorteil, daß es sich lohnt, dieses Risiko einzugehen.
mfg Martin
-
Sicher, aber man kann ja mit
sizeof
nachpruefen. Aber da hier mit Endian argumentiert wird, haengt sowieso viel von aeusseren Umstaenden ab.Der Union bringt Dir keinen nennenswerten Vorteil, daß es sich lohnt, dieses Risiko einzugehen.
Ich finde Bitschiften immer etwas verwirrend.
-
knivil schrieb:
Sicher, aber man kann ja mit
sizeof
nachpruefen. Aber da hier mit Endian argumentiert wird, haengt sowieso viel von aeusseren Umstaenden ab.Der Union bringt Dir keinen nennenswerten Vorteil, daß es sich lohnt, dieses Risiko einzugehen.
Ich finde Bitschiften immer etwas verwirrend.
Ach ja? Und wie reagierst Du, wenn sizeof( word ) != sizeof( endian )?
Was ist am Bitshift verwirrend? Grundregel: kümmere dich beim Bitshift nicht um die Endianess. Das macht der Prozessor für Dich. Einzig und allein die Vorzeichen sind wichtig.
x << 1 ist das selbe wie x * 2
x << 2 ist das selbe wie x * 4
x << 3 ist das selbe wie x * 8u.s.w. u.s.f
vieleicht hilft das, um die Bitshiftoperatoren zu verstehen.
mfg Martin
-
knivil schrieb:
Sicher, aber man kann ja mit
sizeof
nachpruefen. Aber da hier mit Endian argumentiert wird, haengt sowieso viel von aeusseren Umstaenden ab.Der Union bringt Dir keinen nennenswerten Vorteil, daß es sich lohnt, dieses Risiko einzugehen.
Ich finde Bitschiften immer etwas verwirrend.
Aber die ganze Endianessgeschichte ist ohnehin unnötig, wenn man statt unions & Co lieber Bitshifterei benutzt.
Und zu der obigen Castdiskussion: Denkt daran, dass die Datentypen während der Rechnung dank der integral promotion ohnehin vergrößert werden.
-
Wie portabel ist eigentlich dieser Code?
struct Flag { unsigned char f1 : 1; unsigned char f2 : 1; unsigned char f3 : 1; unsigned char f4 : 1; unsigned char f5 : 1; unsigned char f6 : 1; unsigned char f7 : 1; unsigned char f8 : 1; };
Nehmen wir an ich würde ein
unsigned char
über das Netzwerk verschicken. Wäre das portabel? Ist das struct portabel?
-
Der interne Aufbau von bit-fields ist meines Wissens nach implementation defined, ich mag aber gerade nicht die entsprechende Stelle im Standard suchen und zitiere daher bloß aus dem Gedächtnis.
-
Und wenn ich einen unsigned char nehme und ihn manuell mit Bit Manipulationen manipuliere und über das Netzwerk versende. Wäre das portabel?
-
reex schrieb:
Und wenn ich einen unsigned char nehme und ihn manuell mit Bit Manipulationen manipuliere und über das Netzwerk versende. Wäre das portabel?
Ziemlich. Es gibt ein paar exotische Systeme mit CHAR_BIT > 8, aber dies ist extrem selten.
-
SeppJ schrieb:
reex schrieb:
Und wenn ich einen unsigned char nehme und ihn manuell mit Bit Manipulationen manipuliere und über das Netzwerk versende. Wäre das portabel?
Ziemlich. Es gibt ein paar exotische Systeme mit CHAR_BIT > 8, aber dies ist extrem selten.
Das ist gut zu wissen. Diese exotischen Systeme sind für mich glücklicherweise egal. Vielen Dank für die Antwort