Hallo, ich will eine long Variable in ein char Array umwandeln, sodass ich die 4 Bytes der long Variable einzeln verwenden kann und bin überfragt(Anfänger).Ich hoffe ihr könnt mir helfen. Danke
1 | long a = 1234567; |
2 | char b[4]; |
3 | |
4 | b[0] = a >> 24; |
5 | b[1] = a >> 16; |
6 | b[2] = a >> 8; |
7 | b[3] = a; |
Das wäre die Big-Endian-Reihenfolge. Wenn es andersrum sein soll, entsprechend die Positionen bzw. Shifts tauschen.
unsigned char bitte. Für Bytes niemals char verwenden! Bei char überlässt du es dem Compiler, ob da ein Vorzeichen angenommen werden soll oder nicht. Das ist aber nicht das, was man bei Bytes haben will. Bei Bytes gibt es kein Vorzeichen. Daher: sag das auch deinem Compiler und überlasse es nicht dem Zufall bzw. dem Compilerhersteller ob das so ist oder nicht. Das unsigned kostet dich nichts, kann dich aber vor schwer zu findenden Fehlern bewahren, wenn der Compiler Default eben nicht unsigned ist.
Ah ja, genau danach hatte ich gesucht. Vielen Dank für die schnellen Antworten.
Empfehlen würde ich dir auch den Datentyp uint8_t zu verwenden, unsigned char müsste nach Standard zwar sowieso sizeof(unsigned char) == 1 ergeben, aber so bist du immer auf der sicheren Seite.
Johann L. schrieb: > Dieses Type-Punning ist inspecified Behavior in C. Ist es nicht. Nur weil das im Standard als undefiniert beschrieben wird, heisst das noch lange nicht, dass das Verhalten irgendwie zufällig oder nicht reproduzierbar ist. Sondern nur, dass dieser Fall jeder Compiler handhaben kann wie er will (eher sein Entwickler). Der Normalfall ist, dass überschüssige Bits einfach abgeschnitten werden. Bsp.:
1 | unsigned long int valueA=0x1234ABCD; |
2 | unsigned char valueB; |
3 | valueB=valueA; /* in valueB steht nun 0xCD */ |
Zur Sicherheit das Handbuch fragen oder einfach ausprobieren.
Es ist unspecified, nicht implementation defined. "Ausprobieren" ist übrigens n tolls Design Pattern...
be stucki schrieb: > Johann L. schrieb: >> Dieses Type-Punning ist inspecified Behavior in C. > > Ist es nicht. Nur weil das im Standard als undefiniert beschrieben wird, > heisst das noch lange nicht, dass das Verhalten irgendwie zufällig oder > nicht reproduzierbar ist. Sondern nur, dass dieser Fall jeder Compiler > handhaben kann wie er will (eher sein Entwickler). Undefiniertes Verhalten heißt auch, daß er es gar nicht explizit handhaben muß, so daß eben das rauskommt, was sich aus irgendwelchen anderen Umständen ergibt, auch wenn das sich je nach Compiler-Parametern, Optimierung oder anderen Dingen unterschiedlich verhält. Der Compiler-Bauer muß sich schlicht überhaupt nicht drum kümmern und nicht mal drüber nachdenken, was denn in dem Fall passiert. Johann L. schrieb: > Es ist unspecified, nicht implementation defined. Immerhin darf man aber jedes Objekt in ein Array aus unsigned char gleicher Größe per memcpy kopieren, also so:
1 | long a = 1234567; |
2 | char b[sizeof a]; |
3 | |
4 | memcpy(b, a, sizeof a); |
Das dürfte aus ISO-C-Sicht die sauberste Variante sein und beim gcc auch nicht langsamer oder umständlicher als irgendwelche union-Verrenkungen oder Pointer-Castereien.
Rolf Magnus schrieb: > Immerhin darf man aber jedes Objekt in ein Array aus unsigned char > gleicher Größe per memcpy kopieren, also so: > long a = 1234567; > char b[sizeof a]; > > memcpy(b, a, sizeof a); > > Das dürfte aus ISO-C-Sicht die sauberste Variante sein und beim gcc auch > nicht langsamer oder umständlicher als irgendwelche union-Verrenkungen > oder Pointer-Castereien. Wenn man tatsächlich eine Kopie braucht, kann man das natürlich machen. Wenn es nur darum geht, auf einzelne Bytes zuzugreifen, erreicht man mit den "Union-Verrenkungen oder Pointer-Castereien" aber das Gleiche ohne die Daten kopieren zu müssen. Das Problem ist nur (sowohl bei memcpy, Unions und Pointercasting), dass der Code nicht portabel ist, da auf anderer Hardware die Byte-Reihenfolge anders sein kann. Beim Shiften ist die Semantik dagegen unabhängig von der Bytereihenfolge, und bei einem klugen Compiler nicht langsamer als die anderen Methoden.
Streng genommen müsste man die Bits auf der linken Seite auch noch ausmaskieren, weil ja nicht garantiert ist, dass ein char 8 Bit breit ist:
1 | unsigned long a = 1234567; |
2 | unsigned char b[4]; |
3 | |
4 | b[0] = (a >> 24) & 0xFF; |
5 | b[1] = (a >> 16) & 0xFF; |
6 | b[2] = (a >> 8) & 0xFF; |
7 | b[3] = a & 0xFF; |
Das sollte dann wirklich koscher sein. Wenn man es öfters braucht, kann man es ja in ein Macro verpacken.
xfr schrieb: > Wenn man tatsächlich eine Kopie braucht, kann man das natürlich machen. > Wenn es nur darum geht, auf einzelne Bytes zuzugreifen, erreicht man mit > den "Union-Verrenkungen oder Pointer-Castereien" aber das Gleiche ohne > die Daten kopieren zu müssen. Bei der Union mußt du auch kopieren, es sei denn, du verpackst gleich den ursprünglichen long in die Union rein. Ggf. mußt du da sogar zweimal kopieren, nämlich einmal den long in die union, dann das Ergebnis wieder raus in das Ziel-Array. > Das Problem ist nur (sowohl bei memcpy, Unions und Pointercasting), dass > der Code nicht portabel ist, da auf anderer Hardware die > Byte-Reihenfolge anders sein kann. Beim Shiften ist die Semantik dagegen > unabhängig von der Bytereihenfolge, und bei einem klugen Compiler nicht > langsamer als die anderen Methoden. Allerdings ist auch das Rechtsschieben von negativen Werten, wie sie ein long ja haben kann, nicht portabel.
Rolf Magnus schrieb: > Allerdings ist auch das Rechtsschieben von negativen Werten, wie sie ein > long ja haben kann, nicht portabel. Also long erst in einen unsigned long casten, dann schieben ;-) Ich werfe diesen Vorschlag noch ins Feuer:
1 | long a = 1234567; |
2 | unsigned char * b = (unsigned char *) &a; |
Dann kann man mit b[0] bis b[3] auf die 4 Bytes lesend zugreifen. Allerdings hat man hier weder eine Kopie noch ist diese Lösung Endian-fest, dafür aber ist sie wohl die schnellste Lösung ;-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.