Forum: Compiler & IDEs 4 uint8_t in uint32_t konvertieren


von daniel (Gast)


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

von Micha 3.0 (Gast)


Lesenswert?

Hier:

  w = b1 & 0xFF;

koppierst Du doch nur 0xFF in die Varialble.

Bsp:
Denn 10100110 & 11111111 ergibt 11111111

von Alf (Gast)


Lesenswert?

Micha 3.0 schrieb:
> w = b1 & 0xFF;
>
> koppierst Du doch nur 0xFF in die Varialble.

Das wäre bei | so!

von Karl H. (kbuchegg)


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.

von daniel (Gast)


Lesenswert?

Sicher?

Ich dachte immer:
10100110 & 11111111 = 10100110

von PittyJ (Gast)


Lesenswert?

Denn 10100110 & 11111111 ergibt 11111111

Hm, sowie ich die Und-Verknüpfung kenne, ist diese Aussage falsch.


für Daniel:

mach auch den Cast für b2, also

 w |= ((uint32_t)b2) << 8;

von Karl H. (kbuchegg)


Lesenswert?

Micha 3.0 schrieb:
> Hier:
>
>   w = b1 & 0xFF;
>
> koppierst Du doch nur 0xFF in die Varialble.
>
> Bsp:
> Denn 10100110 & 11111111 ergibt 11111111

Falsch.
Ausserdem ist das nicht die Quelle seines Problems.

von daniel (Gast)


Lesenswert?

@Karl-Heinz:

BOMBE ! Vielen Dank für die super Erklärung ! Nun funktioniert es !

Gruss Daniel

von Matthias N. (nippey)


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
}

von Zwie B. (zwieblum)


Lesenswert?

uint8_t b[4]={1,2,3,4};
uint32_t *abc=(uint32_t*)b;

von DirkB (Gast)


Lesenswert?

@Matthias N. und @Zwie Blum

Und wie haltet ihr dass mit der Endianess?

von Zwie B. (zwieblum)


Lesenswert?

Würd' mal vorschlagen, das sollte man beim Befüllen des Arrays klären.

von olf79 (Gast)


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

von Simon K. (simon) Benutzerseite


Lesenswert?

Das Endian Problem hat man auch mit der Union.

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.