Casting uint8 uint16 int8 int16

Gast #3667719
Lesenswert?

Hallo,
wie werden beim Casting die Werte umgewandelt? Wenn ich z.B. int8 0b1111 
1101 habe und das ganze in ein uint16 caste als was wird das 
interpretiert? Hintergrund ist ich habe eine 16 Bit signed Zahl die in 2 
8 Bit Zahlen aufgeteilt ist. Die möchte ich wieder als 16 Bit Zahl 
haben. Momentan mache ich das so. Ich bin mir aber nicht ganz sicher 
ober er immer das richtige macht.
Im receivedBuffer[0] ist das MSB.

temp = 
(int16_t)(((uint16_t)receivedBuffer[0])<<8|(uint16_t)receivedBuffer[1]);
Gruß
Peter
#3668050
Lesenswert?

Peter schrieb:
> Hallo,
> wie werden beim Casting die Werte umgewandelt? Wenn ich z.B. int8 0b1111
> 1101 habe und das ganze in ein uint16 caste als was wird das
> interpretiert? Hintergrund ist ich habe eine 16 Bit signed Zahl die in 2
> 8 Bit Zahlen aufgeteilt ist. Die möchte ich wieder als 16 Bit Zahl
> haben. Momentan mache ich das so. Ich bin mir aber nicht ganz sicher
> ober er immer das richtige macht.
> Im receivedBuffer[0] ist das MSB.
>
> temp =
> (int16_t)(((uint16_t)receivedBuffer[0])<<8|(uint16_t)receivedBuffer[1]);
> Gruß
> Peter


Beim Cast wird überhaupt nichts (nie) umgewandelt, lediglich werden die 
unveränderten Bitmuster anders interpretiert.

Die Casts in deinem Beispiel kannst Du dir im Übrigen komplett sparen, 
die werden (abhängig davon, wie receivedBuffer deklariert ist) nicht 
benötigt. Der Linksshift sorgt durch integer promotion automatisch für 
eine Erweiterung in ein int, das dann problemlos mit dem Oder 
verheiratet wird.

Das hier:
1
emp = (receivedBuffer[0] << 8) | receivedBuffer[1];
macht genau dasselbe.
Gast #3668145
Lesenswert?

Markus F. schrieb:
> Beim Cast wird überhaupt nichts (nie) umgewandelt, lediglich werden die
> unveränderten Bitmuster anders interpretiert.

Die Werte werden beim Casten immer umgewandelt. In manchen Fällen ist 
diese Umwandlung allerdings trivial und effektiv nur eine 
"Uminterpretierung" (z.B. signed int -> unsigned int).
Wenn ich einen int8_t nach int16_t caste, kann es aber gar nicht sein, 
daß der Wert nur anders interpretiert wird, weil schon die Größe eine 
andere ist. Bei unsigned muß noch ein 0-Byte davorgehängt werden, bei 
signed muß eine passende Sign-Extension durchgeführt werden.
#3668155
Lesenswert?

Hallo,
@Markus findet das Aufweiten auf Int auch auf 8 Bit Controller statt? 
Weil hier würde es ja wesentlich mehr Rechenzeit kosten wenn es immer 
gemacht wird.

2. Frage zum Casting: Wie werden "downcast" aufgelöst? Also von uint_16 
nach uint_8? Irgendwie finde ich im Internet fast nur sachen zum 
"upcasten". Ist das verhalten einheitlich definiert(falls ja wo?) oder 
unterscheiden sich da die Compiler/Architekturen?

Gruß
Peter
Gast #3668256
Lesenswert?

Peter Z. schrieb:
> Hallo,
> @Markus findet das Aufweiten auf Int auch auf 8 Bit Controller statt?

Bei einem konformen Compiler ja, aber dieser darf das noch optimieren. 
Er darf die Berechnung auch mit einem kleineren Typ machen, aber nur 
wenn er sicherstellen kann, daß das Ergebnis sich dadurch nicht ändert.

> 2. Frage zum Casting: Wie werden "downcast" aufgelöst? Also von uint_16
> nach uint_8?

Im Prinzip ist es eine Modulo-Operation. ISO C drückt das etwas 
umständlicher aus, indem es sagt, daß so lange wiederholt der 
größtmögliche Wert des Zieltyps + 1 abgzogen wird, bis das Ergebnis 
reinpasst. Das gilt aber nur für vorzeichenlose Typen. Und nein, das 
bedeutet nicht, daß der Compiler wirklich in einer Schleife subtrahieren 
muss.

> Ist das verhalten einheitlich definiert(falls ja wo?)

Das ist definiert in ISO/IEC 9899.

> oder unterscheiden sich da die Compiler/Architekturen?

Bei vorzeichenbehaftetem Zieltyp kann es sich unterscheiden. Da ist das 
ganze laut ISO C "implementation-defined", womit ich wieder was gelernt 
habe. ;-)

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