Forum: Mikrocontroller und Digitale Elektronik frage zum casten von variablen


von Jens (Gast)


Lesenswert?

Hallo,
ich habe eine frage zum casten in C.
1
uint32_t summe;
2
uint16_t summand_A;
3
uint16_t summand_B;
4
5
summand_A = 0xFFFF;
6
summand_B = 0xFFFF;
7
8
summe = (uint32_t)summand_A + (uint32_t)summand_B;

damit erhalte ich mein gewünschtes ergebnis (hier 0x1FFFE).

aber was passiert genau beim casten?
summand_A und summand_B haben ja einene bestimmten Platz und bereich im 
Speicher durch die definition (uint16_t summand_A;) erhalten.

Wird der gesamte speicher vom gecasteten summand_A genommen? Also auch 
die 16 bits die vor der variable stehen? Was ja jetzt uint32_t ist. Was 
ist, wenn da im Speicher irgendwas drinn steht? Dann passt das ergebnis 
ja nicht mehr.

Wenn summand_B jetzt genau hinter summand_A steht und ich es auf 
uint32_t caste, ist dann summand_B=0xFFFFFFFF (Also summand_B und das 
davorstehende summand_A)?

von S. R. (svenska)


Lesenswert?

Jens schrieb:
> Wird der gesamte speicher vom gecasteten summand_A genommen?

Nein, da dein summand_A kein Zeiger auf Speicher ist, sondern ein 
Integer. Mit dem Cast weist du den Compiler an, diesen Integer als 
32-Bit-Integer zu behandeln, und nicht als int-Bit-Integer.

Anders ausgedrückt: Der Compiler lädt deinen uint16_t Wert mit dem 
Cast in ein 32-Bit-Register (natürlich nur virtuell, wenn die CPU sowas 
nicht hat). Es werden also nur 16 Bit geladen und auf 32 Bit aufgebläht.

Eine Folge dessen ist, dass die Addition mit dem Cast natürlich nicht 
mehr auf "int" ausgeführt werden kann, sondern als 32-Bit-Addition 
ausgeführt werden muss, weil jetzt mindestens ein Summand 32 Bit breit 
ist.

Merke: In C hängt die Bitbreite einer Operation nicht vom Ergebnistyp 
ab, sondern von den Eingangstypen.

Einen Unterschied macht das aber nur, wenn "int" nicht ohnehin 32 Bit 
breit ist.

von Einer K. (Gast)


Lesenswert?

Jens schrieb:
> summe = (uint32_t)summand_A + (uint32_t)summand_B;
Explizite Aufweitung der Summanden

summe = 0ul + summand_A + summand_B;
Implizite Aufweitung der Summanden

Jens schrieb:
> Wird der gesamte speicher vom gecasteten summand_A genommen? Also auch
> die 16 bits die vor der variable stehen?
Nein.

von HildeK (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Jens schrieb:
>> summe = (uint32_t)summand_A + (uint32_t)summand_B;
> Explizite Aufweitung der Summanden

Das sind so Feinheiten, die mir auch nicht so deutlich bewusst waren 
(weil ich es sehr selten verwende).
Reicht es in deinem Beispiel auch, wenn nur einer der beiden Summanden 
auf uint32_t aufgeweitet werden? Müsste imho so sein, sonst würde das 
Beispiel mit der impliziten Aufweitung (0ul + ...) auch nicht 
funktionieren?

von Einer K. (Gast)


Lesenswert?

HildeK schrieb:
> Reicht es in deinem Beispiel auch, wenn nur einer der beiden Summanden
> auf uint32_t aufgeweitet werden?
Ja!

Der + Operator ist mehrfach überladen. Auch in C.
C++ geht da noch weiter und erlaubt eigene Überladungen.

Die wirklich ernsten Probleme mit dem Casten gibts z.B. bei Pointern
Denn da wird nur der Pointer modifiziert/umgewandelt und nicht die 
dahinterliegenden Daten.

Die Addition mit 0ul fällt übrigens der Optimierung zum Opfer, nur die 
Typeumwandlung bleibt davon erhalten.

von Jens (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> HildeK schrieb:
>> Reicht es in deinem Beispiel auch, wenn nur einer der beiden Summanden
>> auf uint32_t aufgeweitet werden?
> Ja!

Das wusste ich auch noch nicht.
Aber für mich ist es momentan noch übersichtlicher es einfach vor allen 
parametern zu schreiben.

Arduino Fanboy D. schrieb:
> Die Addition mit 0ul fällt übrigens der Optimierung zum Opfer, nur die
> Typeumwandlung bleibt davon erhalten.

OK, auch nett zu wissen

von Rolf M. (rmagnus)


Lesenswert?

Der +-Operator bekommt bei jeder Nutzung einen bestimmten Datentyp, mit 
dem er arbeitet. Zunächst wird durch Konvertierung sichergestellt, dass 
beide Operanden den selben Typ haben, sofern du unterschiedlche Typen 
übergibst. Das Ergebnis ist dann ebenfalls von diesem Typ. Konvertierung 
heißt, dass ein temporärer Wert des Zieltyps erstellt wird, der nach der 
Operation wider verschwindet. Der ursprünglich übergebene Wert wird dazu 
also nicht angefasst.
Die Wahl des Typs hängt von den Typen der Operanden ab (und niemals 
davon, was später mit dem Ergebnis gemacht wird), aber im Prinzip wird 
der größere Typ genommen, mindestens jedoch int. Das nennt sich "integer 
promotion".

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.