Forum: Compiler & IDEs 64bit Variable in 8x 8bit array schreiben


von Stefan (Gast)


Lesenswert?

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

von dummschwaetzer (Gast)


Lesenswert?

union

von Ingo L. (corrtexx)


Lesenswert?

Stefan schrieb:
> Wie mache ich das am Besten?
Mit einer union
1
union{
2
 uint64_t GrosseVar;
3
 uint8_t Var[8];
4
}

von Yalu X. (yalu) (Moderator)


Lesenswert?

Wenn es portabel sein soll, mit Shifts.

von Ingo L. (corrtexx)


Lesenswert?

Yalu X. schrieb:
> Wenn es portabel sein soll, mit Shifts.
Wohl Dem, der einen Barrelshifter an Bord hat ;)

von pumuggl (Gast)


Lesenswert?

Wenn es wirklich portabel sein soll, natuerlich mit Java.


LOL.

von A. F. (artur-f) Benutzerseite


Lesenswert?

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
    }

von pumuggl (Gast)


Lesenswert?

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.

von Dirk B. (dirkb2)


Lesenswert?

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.

von Dirk B. (dirkb2)


Lesenswert?

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.

von Ingo L. (corrtexx)


Lesenswert?

>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
}

von Thomas W. (goaty)


Lesenswert?

Geht das nicht ?

uint64_t var_64_bit = 0xFFEEDDCCBBAA2211;
*(uint64_t*)&array[0] = var_64_bit;

: Bearbeitet durch User
von pumuggl (Gast)


Lesenswert?

Man koennte die inkriminierte Funktion in VHDL schreiben und dazulinken.

von Ingo L. (corrtexx)


Lesenswert?

Thomas W. schrieb:
> uint64_t var_64_bit = 0xFFEEDDCCBBAA2211;
> *(uint64_t*)&array[0] = var_64_bit;
Das is aber schon mehr als "dirty".

von Dirk B. (dirkb2)


Lesenswert?

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

von Yalu X. (yalu) (Moderator)


Lesenswert?

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)

von Wilhelm M. (wimalopaan)


Lesenswert?

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).

von Wilhelm M. (wimalopaan)


Lesenswert?

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.

von Thomas W. (goaty)


Lesenswert?

Oder vielleicht:

uint64_t a = 0x1234567812345678;
char b[8];
*reinterpret_cast<uint64_t*>(&b[0]) = a;

Ich schau mal was noch schmutziger geht ;-)

von Dirk B. (dirkb2)


Lesenswert?

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.

von Thomas W. (goaty)


Lesenswert?

uint64_t a = 0x1234567812345678;
char b[8];
a = __builtin_bswap64(a);
*reinterpret_cast<uint64_t*>(&b[0]) = a;

von Nop (Gast)


Lesenswert?

Oder man nimmt ganz einfach memcpy.

von Dirk B. (dirkb2)


Lesenswert?

Nop schrieb:
> Oder man nimmt ganz einfach memcpy.

Da bleibt immer noch das Problem mit der Endianess.

von Nop (Gast)


Lesenswert?

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.

von Dirk B. (dirkb2)


Lesenswert?

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
von Jemand (Gast)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Bernd K. (prof7bit)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

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...

von Nop (Gast)


Lesenswert?

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?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

c-hater schrieb:
> wie ein trockener Furz im Seewind.

Da bist du ja der absolute Experte, ganz ohne Zweifel.

von Ingo Less (Gast)


Lesenswert?

Wer glaubt, dass nur weil er c-hater heisst, er kein c kann irrt 
gewaltig...

von c-hater (Gast)


Lesenswert?

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...

von Bernd K. (prof7bit)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

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.

von Heiko L. (zer0)


Lesenswert?

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

von Nop (Gast)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Heiko L. (zer0)


Lesenswert?

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. 
:)

von Heiko L. (zer0)


Lesenswert?

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...

von Nop (Gast)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Heiko L. (zer0)


Lesenswert?

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.

von Carl D. (jcw2)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Stefan (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.