Forum: Mikrocontroller und Digitale Elektronik 32Bit Variable beschreiben


von Verzweifelter (Gast)


Lesenswert?

Hallo,

ich verzweifle gerade beim beschreiben einer 32Bit Variablen ...

1. Versuch
unsigned long test;
test = 0x12345678;

mein Debugger zeigt anschließend im Watch Window den Wert 0x12345678 an.
Test ok

2. Versuch
unsigned long test;
test = ((0x12<<24) | (0x34<<16) | (0x56<<8) | (0x78<<0));
oder
test = ((unsigned long)(0x12<<24) | (0x34<<16) | (0x56<<8) | (0x78<<0));

mein Debugger zeigt 0x00005678 an ... was läuft hier schief?

auch der Compiler schmeißt eine Warning
warning: left shift count >= width of type

Warum?

Gruß

von (prx) A. K. (prx)


Lesenswert?

Verzweifelter schrieb:
> test = ((0x12<<24)

Das geht bei einer 8/16-Bit Kiste in die Hose. Den Grund hat dir der 
Compiler auch genannt. Das ist eine "int" Rechnung. Besser:
  test = ((0x12L<<24)

Und auch das wird erst in "int" berechnet und danach erweitert, zu spät:
> test = ((unsigned long)(0x12<<24)

von Dr. Sommer (Gast)


Lesenswert?

Protip: uint32_t hat immer 32bit, unabhängig von der Architektur ;-)

von Verzweifelter (Gast)


Lesenswert?

Hallo,

danke, jetzt funktioniert es.

Aber was passiert denn da genau? Mit dem L caste ich doch das Byte in 
einen long ... eigentlich müsste es doch dann in die Hose gehen?????

von (prx) A. K. (prx)


Lesenswert?

Verzweifelter schrieb:
> Aber was passiert denn da genau? Mit dem L caste ich doch das Byte in
> einen long ... eigentlich müsste es doch dann in die Hose gehen?????

Wieso? 0x12 nach "long" konvertiert ändert den Wert nicht.

Übrigens ist das L kein Cast, sondern ein Teil der Zahl. Und 0x12 ist 
kein Byte, sondern "int".

von Verzweifelter (Gast)


Lesenswert?

Ahh, ok jetzt klingelts ... vielen Dank :-)

von Hmm (Gast)


Lesenswert?

>eigentlich müsste es doch dann in die Hose gehen
Warum meinst Du das?

Es ist im Gegenteil so, das dieses L (das ist übrigens ein Suffix, der 
den Datentyp anzeigt, jedoch kein cast [nicht im eigentlichen Sinne]) 
gerade das möglich macht, was Du willst.
1
0x12<<24

gucken wir uns mal binär an.

Die 12 ist ein Integer, hat 16 Bit:

0000.0000.0000.1010

Wenn man das 24 mal nach links verschiebt, dann bleibt
0000.0000.0000.0000

denn links von dem 15. Bit ist nichts mehr.

Deswegen warnt Dich auch der Compiler.

Bei
1
0x12L<<24

erhälst Du

0000.0000.0000.0000.0000.0000.0000.1010

was nach dem Schieben um 24 Bit durchaus noch darstellbar ist.

0000.1010.0000.0000.0000.0000.0000.0000

von xfr (Gast)


Lesenswert?

0x12 ist einfach nur eine konstante Zahl (dezimal 18). Standardmäßig ist 
sie so breit wie ein int, also auf Deiner Plattform 16 Bit. So lange sie 
nicht in eine Variable mit anderer Breite gespeichert wird, wird mit ihr 
gerechnet, als ob sie aus einer 16-Bit-Variable käme, also 0x0012. Wenn 
Du das um 16 Stellen nach links schiebst, bleibt nur noch 0x0000. Die 
"Variable" wird nicht automatisch verbreitet, wenn das Ergebnis nicht 
reinpasst. Das ginge zur Laufzeit auch schlecht.

Wenn Du ein L für long dahinter schreibst, wird die Zahl dagegen als 
32-Bit-Konstante betrachet, also als 0x00000012 und entsprechend damit 
gerechnet. Dann klappen auch die Shifts, ohne dass der Wert links 
rausfällt.

von (prx) A. K. (prx)


Lesenswert?

Hmm schrieb:
> Die 12 ist ein Integer, hat 16 Bit:
> 0000.0000.0000.1010

0x12 ist eher
  0000.0000.0001.0010

von Hmm (Gast)


Lesenswert?

@ A.K.

Oh, Sch... Hast recht. Danke für den Hinweis.

Es muss also heissen:

0x12<<24

gucken wir uns mal binär an.

Die 12 ist ein Integer, hat 16 Bit:

0000.0000.0001.0010

Wenn man das 24 mal nach links verschiebt, dann bleibt
0000.0000.0000.0000

denn links von dem 15. Bit ist nichts mehr.

Deswegen warnt Dich auch der Compiler.

Bei

0x12L<<24

erhälst Du

0000.0000.0000.0000.0000.0000.0001.0010

was nach dem Schieben um 24 Bit durchaus noch darstellbar ist.

0001.0010.0000.0000.0000.0000.0000.0000

von Verzweifelter (Gast)


Lesenswert?

Was würde ein L hinter der Zahl auf einer 32Bit Maschine machen ... ?
Dann ist es doch 64Bit, oder?

Wie würde ich die Sache generisch programmieren?

von (prx) A. K. (prx)


Lesenswert?

Verzweifelter schrieb:
> Was würde ein L hinter der Zahl auf einer 32Bit Maschine machen ... ?
> Dann ist es doch 64Bit, oder?

Im 32-Bit Programmiermodell (LP32) eher selten. Und auch bei 64-Bit 
Maschinen im 64-Bit Programmiermodell nur in Linux (LP64), nicht aber 
bei Microsoft (LLP64).

http://www.unix.org/version2/whatsnew/lp64_wp.html

> Wie würde ich die Sache generisch programmieren?

Der Einfachheit halber L verwenden. In LP64 ist das dann zwar 64 Bit 
breit, aber das dann auf 32 Bits runter zu konvertieren ist kein 
Problem.

Wenn du Variablen von stets exakt 32 Bits brauchst: Wie schon erwähnt 
unbedingt (u)int32_t als Datentyp verwenden.

von Verzweifelter (Gast)


Lesenswert?

super, danke

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.