mikrocontroller.net

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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Stefan (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
-2 lesenswert
nicht lesenswert
union

von Ingo L. (corrtexx)


Bewertung
-2 lesenswert
nicht lesenswert
Stefan schrieb:
> Wie mache ich das am Besten?
Mit einer union
union{
 uint64_t GrosseVar;
 uint8_t Var[8];
}

von Yalu X. (yalu) (Moderator)


Bewertung
5 lesenswert
nicht lesenswert
Wenn es portabel sein soll, mit Shifts.

von Ingo L. (corrtexx)


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

von pumuggl (Gast)


Bewertung
-5 lesenswert
nicht lesenswert
Wenn es wirklich portabel sein soll, natuerlich mit Java.


LOL.

von A. F. (artur-f) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Yalu X. schrieb:
> Wenn es portabel sein soll, mit Shifts.
Jo, ich würde es auch so machen.
 uint8_t array[8];
 uint64_t var_64_bit = 0xFFEEDDCCBBAA2211;
    
    for (char i = 0; i < 8; i++) {
      array[i] =  (uint8_t)(var_64_bit >> (i * 8));
    }

von pumuggl (Gast)


Bewertung
-4 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
>Wenn es portabel sein soll, mit Shifts.
uint64_t var_64_bit_dummy = 0;
var_64_bit_dummy  = var_64_bit;
for (uint8_t ByteNr = 0; ByteNr < 8; ByteNr++){
 Array[ByteNr] = (uint8_t)(var_64_bit_dummy & 0xff);
 var_64_bit_dummy /= 256;  
}

von Thomas W. (goaty)


Bewertung
-1 lesenswert
nicht lesenswert
Geht das nicht ?

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

: Bearbeitet durch User
von pumuggl (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Man koennte die inkriminierte Funktion in VHDL schreiben und dazulinken.

von Ingo L. (corrtexx)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Thomas W. schrieb:
> *(uint64_t*)&array[0] = var_64_bit;

Das verstößt gegen die "strict aliasing rule", die da lautet:

An object shall have its stored value accessed only by an lvalue
expression that has one of the following types:

- a type compatible with the effective type of the object,

- a qualified version of a type compatible with the effective type of the
  object,

- a type that is the signed or unsigned type corresponding to the
  effective type of the object,

- a type that is the signed or unsigned type corresponding to a qualified
  version of the effective type of the object,

- an aggregate or union type that includes one of the aforementioned
  types among its members (including, recursively, a member of a
  subaggregate or contained union), or

- a character type.

(Quelle: ISO/IEC 9899:2017 Programming Languages — C, N2176)

von Wilhelm M. (wimalopaan)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


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

von Nop (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Oder man nimmt ganz einfach memcpy.

von Dirk B. (dirkb2)


Bewertung
1 lesenswert
nicht lesenswert
Nop schrieb:
> Oder man nimmt ganz einfach memcpy.

Da bleibt immer noch das Problem mit der Endianess.

von Nop (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
-6 lesenswert
nicht 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)


Bewertung
5 lesenswert
nicht 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


Bewertung
0 lesenswert
nicht lesenswert
c-hater schrieb:
> wie ein trockener Furz im Seewind.

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

von Ingo Less (Gast)


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

von c-hater (Gast)


Bewertung
-3 lesenswert
nicht 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)


Bewertung
1 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Nop schrieb:
> Was genau glaubst Du eigentlich, wofür "uint8_t" steht? Seit ZWEI
> JAHRZEHNTEN?

Für eine Zahl <256.
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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
1 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
2 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Hallo...
Erstmal vielen Dank dafür...

Ich habe es jetzt so gemacht:
uint8_t array[8];
 uint64_t var_64_bit = 0xFFEEDDCCBBAA2211;
    
    for (char i = 0; i < 8; i++) {
      array[i] =  (uint8_t)(var_64_bit >> (i * 8));
    }


Das läuft prima...
Vielen Dank dafür.

Wollte jetzt hier keine Grundsatzdiskussion vom Zaun brechen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.