4 uint8_t in uint32_t konvertieren

Gast #2351528
Lesenswert?

Hi,

ich möchte gerne 4 uint8_t Variablen in eine uint32_t Variable 
konvertieren, folgenden Testcode habe ich geschrieben:

#include <avr/io.h>
#include <stdint.h>
1
int main() {
2
  uint8_t b1, b2, b3, b4;
3
  uint32_t w;
4
  
5
  b1 = 0xBC;
6
  b2 = 0x11;
7
  b3 = 0x33;
8
  b4 = 0x44;
9

10
  w = b1 & 0xFF;
11
  w |= b2 << 8;
12
  w |= (uint32_t)b3 << 16;
13
  w |= (uint32_t)b4 << 24;
14
}

Funktioniert eigentlich auch, aber wenn ich b2 auf z.B. A9 abändere, 
dann sind die höheren 16 Bit in w immer FFFF. Wieso?

Gruss Daniel
#2351543
Lesenswert?

Weil du hier ein Zwischenergebnis hast

w |= b2 << 8;


Die Reihenfolge der Ereignisse ist:

b2 auf int (16-Bit signed) aufblasen. Dies deshalb, weil ein 16 Bit 
signed int alle Werte eines uint8_t aufnehmen kann

Damit hast du einen int mit dem Wert 0x00A9

Dieser int wird nun um 8 Stellen nach links verschoben und wird somit zu

0xA900

Aber Achtung: Es ist immer noch ein 16 BIt Wert mit Vorzeichen. Und als 
solcher ist er im 2-er Komplement negativ.

Jetzt wird dieser int dem w 'zugewiesen'.
Du w ein uint32_t ist, wird zunächste der 16 Bit int auf 32 Bit 
aufgeblasen. Und jetzt passierts. Da 0xA900 einen negativen 2-er 
Komplement-Wert darstellt, lautet der entsprechende 32-Bit signed Wert 
dazu 0xFFFFA900

Und so kommen deine 0xFFFF in die höherwertigen 16 BIt.

Caste b2 zuerst auf einen 16 Bit unsigned

w |= (uint16_t)b2 << 8;

Ich denke, das sollte dem Spuk Einhalt gebieten.
#2351573
Lesenswert?

Ich mache sowas gerne mit unions, finde ich schön übersichtlich:
1
union bitMix { 
2
  // 4 x 8bit 
3
  struct achtBit_t { 
4
    uint8_t a, b, c, d;
5
  } achtBit;
6
 
7
  // 1 x 32bit 
8
  uint32_t abcd; 
9
};
10

11
int main(void) { 
12
  bitMix mix1;
13
  mix1.achtBit.a = 0xDE;
14
  mix1.achtBit.b = 0xAD;
15
  mix1.achtBit.c = 0xBE;
16
  mix1.achtBit.d = 0xEF;
17

18
  mix1.abcd = 0xDEADBEEF;
19
}
Gast #2359052
Lesenswert?

warum nicht einfach so:

union _u8_u32 {uint8_t b[4];  uint32_t dw; } val;

val.b[0] = 0xBC;
val.b[1] = 0x11;
val.b[2] = 0x33;
val.b[3] = 0x44;

und man hat in val.dw den u32-Wert stehen.

Die Endianess muss man natürlich in der Befüll-Reihenfolge 
berücksichtigen..

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren