Hallo, irgendwie stehe ich auf dem Schlauch... Ich habe eine 64bit große Variable . Die möchte ich nun in ein 8 byte großes Array schreiben. Wie mache ich das am Besten? Beispiel: var_64_bit = irgendein riesengroßer wert; array[0] = 1. 8 bits der variable also Bit0 bis Bit7 von "var_64_bit" array[1] = 2. 8 bits der variable array[2] = 3. 8 bits der variable array[3] = 4. 8 bits der variable array[4] = 5. 8 bits der variable array[5] = 6. 8 bits der variable array[6] = 7. 8 bits der variable array[7] = 8. 8 bits der variable Danke für die Hilfe. Stefan
Stefan schrieb: > Wie mache ich das am Besten? Mit einer union
1 | union{ |
2 | uint64_t GrosseVar; |
3 | uint8_t Var[8]; |
4 | }
|
Yalu X. schrieb: > Wenn es portabel sein soll, mit Shifts. Wohl Dem, der einen Barrelshifter an Bord hat ;)
Wenn es wirklich portabel sein soll, natuerlich mit Java. LOL.
Yalu X. schrieb: > Wenn es portabel sein soll, mit Shifts. Jo, ich würde es auch so machen.
1 | uint8_t array[8]; |
2 | uint64_t var_64_bit = 0xFFEEDDCCBBAA2211; |
3 | |
4 | for (char i = 0; i < 8; i++) { |
5 | array[i] = (uint8_t)(var_64_bit >> (i * 8)); |
6 | }
|
Damit man genau solchen Krampf nicht mit shifts machen muss, gibt es Unions. Falls auf einer der Zielarchitekturen die Endianess nicht passt, muss man halt mal kurz umschalten. Ernsthafte Compiler haben da Pragmas dafuer.
Ingo L. schrieb: > Yalu X. schrieb: >> Wenn es portabel sein soll, mit Shifts. > Wohl Dem, der einen Barrelshifter an Bord hat ;) Oder einen Compiler der optimieren darf und kann. Dann wird Byte-weise zugegriffen und nicht geschoben.
pumuggl schrieb: > Damit man genau solchen Krampf nicht mit shifts machen muss, > gibt es Unions. Dafür sind unions nicht gedacht. Der Compiler kann das optimieren, wenn er darf.
>Wenn es portabel sein soll, mit Shifts.
1 | uint64_t var_64_bit_dummy = 0; |
2 | var_64_bit_dummy = var_64_bit; |
3 | for (uint8_t ByteNr = 0; ByteNr < 8; ByteNr++){ |
4 | Array[ByteNr] = (uint8_t)(var_64_bit_dummy & 0xff); |
5 | var_64_bit_dummy /= 256; |
6 | }
|
Geht das nicht ? uint64_t var_64_bit = 0xFFEEDDCCBBAA2211; *(uint64_t*)&array[0] = var_64_bit;
:
Bearbeitet durch User
Thomas W. schrieb: > uint64_t var_64_bit = 0xFFEEDDCCBBAA2211; > *(uint64_t*)&array[0] = var_64_bit; Das is aber schon mehr als "dirty".
Ingo L. schrieb: > Thomas W. schrieb: >> uint64_t var_64_bit = 0xFFEEDDCCBBAA2211; >> *(uint64_t*)&array[0] = var_64_bit; > Das is aber schon mehr als "dirty". Das kann zum einen schief gehen, wenn das Alignement nicht passt, desweiteren muß die Endianess nicht passen. Darum Shift
Thomas W. schrieb: > *(uint64_t*)&array[0] = var_64_bit; Das verstößt gegen die "strict aliasing rule", die da lautet:
1 | An object shall have its stored value accessed only by an lvalue |
2 | expression that has one of the following types: |
3 | |
4 | - a type compatible with the effective type of the object, |
5 | |
6 | - a qualified version of a type compatible with the effective type of the |
7 | object, |
8 | |
9 | - a type that is the signed or unsigned type corresponding to the |
10 | effective type of the object, |
11 | |
12 | - a type that is the signed or unsigned type corresponding to a qualified |
13 | version of the effective type of the object, |
14 | |
15 | - an aggregate or union type that includes one of the aforementioned |
16 | types among its members (including, recursively, a member of a |
17 | subaggregate or contained union), or |
18 | |
19 | - a character type. |
(Quelle: ISO/IEC 9899:2017 Programming Languages — C, N2176)
pumuggl schrieb: > Damit man genau solchen Krampf nicht mit shifts machen muss, > gibt es Unions Ich kann dem originalen Post des TO nicht entnehmen, ob es C oder C++ sein soll. Bei C++ geht es mit unions so auf keinen Fall, denn man müsste dort das active-member der union explizit ändern (oder gleich std::variant benutzen).
pumuggl schrieb: > Damit man genau solchen Krampf nicht mit shifts machen muss Shifts sind der einzig in allen Fällen korrekte Weg es zu machen.
Oder vielleicht: uint64_t a = 0x1234567812345678; char b[8]; *reinterpret_cast<uint64_t*>(&b[0]) = a; Ich schau mal was noch schmutziger geht ;-)
Thomas W. schrieb: > Oder vielleicht: > > uint64_t a = 0x1234567812345678; > char b[8]; > *reinterpret_cast<uint64_t*>(&b[0]) = a; > > Ich schau mal was noch schmutziger geht ;-) Da bleibt immer noch das Problem mit der Endianess.
uint64_t a = 0x1234567812345678; char b[8]; a = __builtin_bswap64(a); *reinterpret_cast<uint64_t*>(&b[0]) = a;
Nop schrieb: > Oder man nimmt ganz einfach memcpy. Da bleibt immer noch das Problem mit der Endianess.
Dirk B. schrieb: > Nop schrieb: >> Oder man nimmt ganz einfach memcpy. > > Da bleibt immer noch das Problem mit der Endianess. Dazu kann man Macros wie HostToNetwork oder so nehmen, also wenn man es überhaupt portabel braucht.
Nop schrieb: > Dazu kann man Macros wie HostToNetwork oder so nehmen, also wenn man es > überhaupt portabel braucht. Die wandelt in Big-Endian um. Du müsstest also schon beim schreiben wissen, welche Endianess das System hat. Das fällt beim shiften weg.
:
Bearbeitet durch User
Thomas W. schrieb: > Oder vielleicht: > > uint64_t a = 0x1234567812345678; > char b[8]; > *reinterpret_cast<uint64_t*>(&b[0]) = a; > > Ich schau mal was noch schmutziger geht ;-) Lass die Finger von Konstrukten, die du nicht verstehst.
pumuggl schrieb: > Damit man genau solchen Krampf nicht mit shifts machen muss, > gibt es Unions. Nein. Sie wurden zwar so oft dafür missbraucht, dass das in C irgendwann mal auch erlaubt wurde, aber gedacht waren sie dafür nicht. > Falls auf einer der Zielarchitekturen die Endianess nicht passt, muss man > halt mal kurz umschalten. > Ernsthafte Compiler haben da Pragmas dafuer. Ernsthafte Programmierer nutzen keine proprietären Compiler-Erweiterungen für etwas, das auch portabel geht.
Dirk B. schrieb: > Dafür sind unions nicht gedacht. > Der Compiler kann das optimieren, wenn er darf. Es kommt auf die Sprache an, in C ist type punning mit unions explizit erlaubt, in C++ nicht.
Yalu X. schrieb: > Das verstößt gegen die "strict aliasing rule", die da lautet: [...] Und wieder mal die Bibel zitiert... Es gibt auch Andersgläubige, für die die C-Bibel soviel wert ist wie ein trockener Furz im Seewind. Davon mal abgesehen: der TO hat sich weder auf eine Sprache festgelegt noch hat er spezifiziert, dass er die Einzelbytes in dem Array in einer bestimmten Reihenfolge haben möchte. Damit ist sowieso alles offen und jede, wirklich jede Lösung richtig, sofern sie nur die 64Bit irgendwie in 8Bytes zerlegt... C ist dafür sowieso vollkommen ungeeignet, weil in dieser Dreckssprache Bytes überhaupt nicht existieren, jedenfalls nicht in der Form, wie sie heutzutage jeder geistig Normale versteht, nämlich als Ansammlung von 8Bits...
c-hater schrieb: > Es gibt auch Andersgläubige, für die die C-Bibel soviel wert ist wie ein > trockener Furz im Seewind. Die programmieren dann kein C und wundern sich, wenn ihr kaputter Code auf einmal zerbricht. > C ist dafür sowieso vollkommen ungeeignet, weil in dieser Dreckssprache > Bytes überhaupt nicht existieren, jedenfalls nicht in der Form, wie sie > heutzutage jeder geistig Normale versteht, nämlich als Ansammlung von > 8Bits... Was genau glaubst Du eigentlich, wofür "uint8_t" steht? Seit ZWEI JAHRZEHNTEN?
c-hater schrieb: > wie ein trockener Furz im Seewind. Da bist du ja der absolute Experte, ganz ohne Zweifel.
Wer glaubt, dass nur weil er c-hater heisst, er kein c kann irrt gewaltig...
Nop schrieb: > Was genau glaubst Du eigentlich, wofür "uint8_t" steht? Seit ZWEI > JAHRZEHNTEN? Und wo genau kam uint8_t im OT vor? Der Mann will Bytes. Und in praktisch jeder Sprache außer C/C++ kann er Bytes bekommen...
c-hater schrieb: > Nop schrieb: > >> Was genau glaubst Du eigentlich, wofür "uint8_t" steht? Seit ZWEI >> JAHRZEHNTEN? > > Und wo genau kam uint8_t im OT vor? Der Mann will Bytes. Und in > praktisch jeder Sprache außer C/C++ kann er Bytes bekommen... Jetzt machst Du Dich lächerlich. Manchmal kann man zwar noch schmunzeln wenn Du wieder mal so nen wortgewaltigen Ausbruch wie oben hast, aber das jetzt war irgendwie völliger Käse.
Bernd K. schrieb: > aber > das jetzt war irgendwie völliger Käse. Du hast die Bibel also nicht gelesen. Das kostet zehn Ave Richie. Mindestens.
Nop schrieb: > Was genau glaubst Du eigentlich, wofür "uint8_t" steht? Seit ZWEI > JAHRZEHNTEN? Für eine Zahl <256.
1 | Since the standard does not require uint8_t to be a character type, you could imagine a compiler vendor deliberately making it a separate type to be able to take advantage of the strict aliasing rule. |
https://gist.github.com/jibsen/da6be27cde4d526ee564
Heiko L. schrieb: > Für eine Zahl <256. Mit 8 bit, was man als Byte bezeichnet. Auf Systemen, wo ein Byte nicht 8 Bit hätte, gäbe es diesen Datentyp deswegen nicht. Der Rest des Artikels dreht sich lediglich darum, daß die Aliasing-Regeln für uint8_t nicht wie für char gelten, was aber auch nicht notwendig ist.
c-hater schrieb: > Es gibt auch Andersgläubige, für die die C-Bibel soviel wert ist wie ein > trockener Furz im Seewind. Ein internationaler ISO-Standard ist keine Bibel, und programmieren hat nicht viel mit glauben zu tun, sondern damit, eine Spezifikation zu verstehen und korrekt anzuwenden. Wer sich dazu entschließt, was anderes zu "glauben" als das, was in der Spezifikation steht, wird natürlich auch nichts auf die Reihe bekommen.
Nop schrieb: > Heiko L. schrieb: > >> Für eine Zahl <256. > > Mit 8 bit, was man als Byte bezeichnet. Auf Systemen, wo ein Byte nicht > 8 Bit hätte, gäbe es diesen Datentyp deswegen nicht. Der Rest des > Artikels dreht sich lediglich darum, daß die Aliasing-Regeln für uint8_t > nicht wie für char gelten, was aber auch nicht notwendig ist. Wenn man nicht uint8_t* nimmt, um einfach im Speicher rumzulesen schon. :)
Rolf M. schrieb: > c-hater schrieb: >> Es gibt auch Andersgläubige, für die die C-Bibel soviel wert ist wie ein >> trockener Furz im Seewind. > > Ein internationaler ISO-Standard ist keine Bibel, und programmieren hat > nicht viel mit glauben zu tun, sondern damit, eine Spezifikation zu > verstehen und korrekt anzuwenden. Je nachdem, ob das Komittee dann noch ein paar Definitionen nachreicht, oder entschließt, eine Definitionslücke für Optimierungen zu verwenden...
Heiko L. schrieb: > Wenn man nicht uint8_t* nimmt, um einfach im Speicher rumzulesen schon. > :) Das sollte man nicht tun. Wäre ja auch nicht sinnvoll, wenn uint8_t alles aliasen würde, weil das dann numerische Berechnungen verlangsamen könnte. Für sowas nimmt man char* und stellt im Sinne der Portabilität erstmal sicher, daß das überhaupt 8 bit sind. Byteweises Lesen ergibt schließlich nur Sinn auf Architekturen, wo es überhaupt Bytes gibt (was allerdings heute der Normalfall ist). Aber C kann man eben auch auf CPUs loslassen, die anders aufgebaut sind.
Nop schrieb: > Byteweises Lesen ergibt > schließlich nur Sinn auf Architekturen, wo es überhaupt Bytes gibt (was > allerdings heute der Normalfall ist). Bytes gibt es überall. Sie sind nur nicht zwingend 8 Bit breit. Und nein, das ist keine C-Spezialität.
Nop schrieb: > Das sollte man nicht tun. Wäre ja auch nicht sinnvoll, wenn uint8_t > alles aliasen würde, weil das dann numerische Berechnungen verlangsamen > könnte. Naja, den typedef kann man schnell nachlesen. Das ist eben der Punkt. C!=C.
c-hater schrieb: > Nop schrieb: > >> Was genau glaubst Du eigentlich, wofür "uint8_t" steht? Seit ZWEI >> JAHRZEHNTEN? > > Und wo genau kam uint8_t im OT vor? Der Mann will Bytes. Und in > praktisch jeder Sprache außer C/C++ kann er Bytes bekommen... Echt, in C++17 muß er noch std:: vor das byte schreiben.
Ingo Less schrieb: > Wer glaubt, dass nur weil er c-hater heisst, er kein c kann irrt > gewaltig... Wer glaubt, daß er C kann, nur weil er die Syntax kennt, irrt auch gewaltig.
Hallo... Erstmal vielen Dank dafür... Ich habe es jetzt so gemacht:
1 | uint8_t array[8]; |
2 | uint64_t var_64_bit = 0xFFEEDDCCBBAA2211; |
3 | |
4 | for (char i = 0; i < 8; i++) { |
5 | array[i] = (uint8_t)(var_64_bit >> (i * 8)); |
6 | } |
Das läuft prima... Vielen Dank dafür. Wollte jetzt hier keine Grundsatzdiskussion vom Zaun brechen.
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.