[gelöst] uint32_t in byte zerlegen

Hallo Arduino-Gemeinde,

ich habe einen Zähler als uint32_t. Also uint32_t zaehler = 1002003;
und davon brauche ich jetzt die unteren 3 byte, also byte z[0] , byte z[1] , byte z[2].

Wie mach ich das am einfachsten, dass ich den uint32 in die enzelnen byte zerlegt bekomme?

Herzlichen Dank für eure Unterstützung.

LG Stefan

da sollte ein einfaches shiften reichen

uint32_t zaehler = 1002003;
byte z[4];

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  z[0]=zaehler;
  z[1]=zaehler>>8;
  z[2]=zaehler>>16;
  z[3]=zaehler>>24;


  Serial.println(zaehler, BIN);
  for (auto &i : z)
    Serial.println(i, BIN);
}

void loop() {
  // put your main code here, to run repeatedly:

}

yeep:

765432107654321076543210
    11110100101000010011
                   10011
         1001010
    1111
0

Hallo noiasca,
herzlichen Dank.
noch ne kurze Frage: bleibt die Variable 'zaehler' , wenn ich sie so durch schieben zerlege, unverändert?

LG Stefan

Danke nochmals noiasca,

alles klar. wollte nur ganz sicher sein, da der zaehler noch weiter so gebraucht wird, wie er grad ist.

Ich kanns im Moment nicht testen, hab grad keinen arduino oder kompatiblen frei, eine Lieferung mit Nanos ist noch ausstehend, und das Zielsystem ist noch nicht ganz betriebsbereit.

Du hast mir sehr gehofen. Deine Hilfe sehe und nehme ich als Lösung meines Problems.

LG Stefan

Du kannst auch union nehmen und spart noch Platz

union u32_2_byte{
   uint32_t temp_u32; 
   byte temp_byte[4] ;
} u;

u.temp_u32 = 1002003;
Serial.write(u.temp_byte[0]); 
Serial.write(u.temp_byte[1]);
Serial.write(u.temp_byte[2]);
Serial.write(u.temp_byte[3]);

Auch eine Lösung
Gruß
DerDani

Du kannst auch union nehmen

Das mag beim Avr Gcc noch gelingen.
Aber beim wechsel des Compilers, oder auch beim nächsten Update des Gcc kann damit Schluss sein.
Und schon gar nicht funktioniert es µC übergreifend.

Das Verhalten ist "Implementation defined"
Suchtipp: "gcc abi" oder "Itanium C++ ABI"

Hallo,

das man union nicht mehr verwenden soll hatte ich auch schon gelesen.
Was soll man als Ersatz verwenden?
variant kennt mein gcc nicht. Deiner?
Ich sehe aktuell keine Alternative.

Was soll man als Ersatz verwenden?

Binäre Operatoren!
<< >> & |

Hallo,

also muss man sich das union aus struct oder array basteln und dann die gewünschten Einzelwerte verknüpfen.
Wird sehr umständlich im Vergleich zu union.
Naja gut.

also muss man sich das union aus struct oder array basteln

Verstehe ich nicht....
Die binäre Repräsentation von structs ist auch implementation defined.
Einzig das beibehalten der Reihenfolge ist definiert. Aber genau das ist dann auch Teil des Problems.

structs unterliegen also den selben Bedingungen (Endianness,Alligment,ByteSize)

Hallo combie,
ich nutze das um aus einem float 4 Bytes zu machen. Das geht dann nicht so einfach mit dem Shiften.
Wie macht man das am besten und speichersparendsten.

Mich interressiert wo es die Info gibt das man union nicht mehr verwenden soll. Durch einfach googlen nix vernünftiges gefunden. Ich will mir ja keine "obsoleten" Arbeitsweisen aneignen.

Gruß
DerDani

ich nutze das um aus einem float 4 Bytes zu machen. Das geht dann nicht so einfach mit dem Shiften.

Das geht genauso. Du kannst auch erst mal durch einen reintepret_cast aus einem Float einen uint32_t machen

Mich interressiert wo es die Info gibt das man union nicht mehr verwenden soll.

Oh!
Das steht natürlich nirgendwo, dass man union nicht verwenden soll.
Und mit "nicht mehr" hat das sowieso nichts zu tun.
Da hat sich (in C++) noch nie was geändert.

union ist oft das Mittel der Wahl, wenn sich verschiedene Programmteile einen Speicherbereich teilen müssen/sollen. Der gegenseitige Ausschluss muss dann durch einen Mutex oder Semaphore geregelt werden.

Was dann aber schon mal zu finden ist:

Verwende union nicht zur Type Konvertierung!

Suchtipp: "type punning union"

union ist oft das Mittel der Wahl, wenn sich verschiedene Programmteile einen Speicherbereich teilen müssen/sollen. Der gegenseitige Ausschluss muss dann durch einen Mutex oder Semaphore geregelt werden

Zumindest das "oft" würde ich sehr anzweifeln.
So knapp sollte RAM selten sein, dass man ihn für völlig unabhängige Sachen fast gleichzeitig (so dass man das über Semaphore verriegelt) verwendet.

Ich zumindest habe unions, wenn überhaupt, nur als Ersatz/alternative Schreibweise für reinterpret cast auf andere Zeigertypen verwendet. Üblicherweise, um Strukturen oder größere Datentypen als Bytearray zu behandeln.

Zumindest das "oft" würde ich sehr anzweifeln.

Die Alternative wäre, dynamische Speicherverwaltung.

Weis nicht, wie es bei dir/euch aussieht, aber wenn ich die Wahl habe, zwischen den beiden Fehlern, dann wähle ich öfter die union.

Ich zumindest habe unions, wenn überhaupt, nur als Ersatz/alternative Schreibweise für reinterpret cast auf andere Zeigertypen verwendet. Üblicherweise, um Strukturen oder größere Datentypen als Bytearray zu behandeln.

Und damit steckst du mit beiden Beinen im "Implementation defined behavior"
Entweder hat dir Sorgfalt, oder das Glück, .....

It's undefined behavior to read from the member of the union that wasn't most recently written. Many compilers implement, as a non-standard language extension, the ability to read inactive members of a union

Quelle

Der Gcc unterstützt das.
Aber auch nur innerhalb eines Programms.
Das kann/wird je nach Compiler Version, Optimierungseinstellungen, µC Type/Hersteller usw. unterschiedlich implementiert sein.
Datenübertragungen, zwischen Systemen, sollte man so nicht tun.

Generell muss man bei der Aufgabe " uint32_t in byte[s] zerlegen " es entweder wissen, wie das große Element im Speicher abgelegt ist, oder es halt selber machen mit mehreren Shift- und Maskier-Anweisungen. Bei Datenübertragung dann das gleiche auf dem Zielsystem.

Bei kleinen µControllern würde ich sowieso nicht zu weit von der Hardware abstrahieren, dann ist das Schreckgespenst "implementation defined behavior" nicht gar so schlimm. Nennen wir das Glück eben "Sorgfalt" :slight_smile:

Wenn man RAM nur kurzzeitig braucht und der Inhalt danach geändert werden darf, sind meist lokale Variable das einfachste.

Eine passende Aufgabenstellung ( verschiedene Spiele, mit unterschiedlichen RAM-Strukturen ) hatten wir doch erst vor kurzem hier. Statt reinterpretiertem void* oder byte raw[256] wäre union sehr hübsch gewesen.

Eine passende Aufgabenstellung ( verschiedene Spiele, mit unterschiedlichen RAM-Strukturen ) hatten wir doch erst vor kurzem hier. Statt reinterpretiertem void* oder byte raw[256] wäre union sehr hübsch gewesen.

Durchaus!

Da sicherlich nicht 2 Spiele gleichzeitig gespielt werden, und eine Kommunikation zwischen den Spielen nicht über das Array läuft, ist die Bedingung:

It's undefined behavior to read from the member of the union that wasn't most recently written.

Problemlos einzuhalten.
Es ist also völlig legitim an der Stelle union einzusetzen.

Man könnte sagen: Dafür wurde union erfunden.