C++ Teil 4 – Datentypecasting

Inhalt

Typecasting
Automatisches Typecasting
Manuelles Typecasting
Übungsaufgaben

Typecasting

Nein. Das ist kein Casting im Sinne von „Deutschland sucht die Variable“, vielmehr bedeutet dieser Begriff Umformung(eng: to cast – formen). In unserem Fall geht es um die Umformung von einem Datentyp zu dem anderen (z.B. short zu long).

Als erstes muss man wissen, dass C++ eine typsichere Sprache ist. Das bedeutet, dass C++ immer überprüft ob die Datentypen zueinander kompatibel sind, wenn man mit Variablen verschiedener Datentypen rechnet. Versucht man einer short-Variable einen double-Wert zu zuweisen, gibt der Compiler eine Warnmeldung aus, dass es zu Informationsverlust kommen kann. Der Compiler-Prozess wird aber nicht gestoppt. Deswegen sollte man besonders auf die Warnungen achten, denn diese weisen oft auf einen (zukünftigen) Fehler hin.

double var_1 = 343434.455;
short ergebnis = 0;

ergebnis = var_1; // warnung

Folgender Code macht keine Probleme, aber nur weil C++ eine automatische Typumwandlung besitzt.

double ergebnis = 0;
short zahl_1 = 345;
int zahl_2 = 5664;
float zahl_3 = 56.4234f;

ergebnis = zahl_1 + zahl_2 + zahl_3;

Der Grund dafür ist ein Mechanismus in den C++ Compilern: automatisches Typecasting.

Automatisches Typecasting

birneAutomatisches Datentype-Casting wird auch als implizites Casting bezeichnet.

Das automatische Umwandeln erfolgt immer dann, wenn ein Typ mit keinem Zahlenbereich bzw. kleinerer Genauigkeit in einen Datentyp mit dem größeren Zahlenbereich bzw. größere Genauigkeit konvertiert wird. Mit anderen Worten ausgedrückt, automatische Konvertierung wird immer dann durchgeführt, wenn bei der Konvertierung keine Daten verloren gehen.

Die automatische Konvertierung erfolgt nach folgendem Schema:

auto_casting
Automatisches Datentypecasting in C++

Wird eine Umwandlung entgegen der aufgeführten Reihenfolge benötigt, so muss der Programmierer selbst eine Entscheidung treffen.

Manuelles Typecasting

birneManuelles Datentype-Casting wird auch als explizites Casting bezeichnet.

Durch manuelles Casting erzwingt man eine Typeumwandlung. Wozu man das braucht?
Dazu zwei Beispiele:

int euro = 10;
int personen = 3;

 // 10 Euro auf 3 Personen teilen (float = int/int)
float euro_pro_person = euro / personen;

cout<<"euro_pro_person: "<< euro_pro_person <<endl;

Wohin ist ein Euro verschwunden?

int euro = 11;
int personen = 3;

 // 11 Euro auf 3 Personen teilen (float = int/int)
float euro_pro_person = euro / personen;

cout<<"euro_pro_person: "<< euro_pro_person <<endl;

Jetzt hat jede Person 4 Euro in der Tasche, was natürlich nicht sein kann.

Dieses zunächst willkürlich erscheinende Verhalten ist leicht zu erklären. Bei einer Division von zwei Integer-Variablen geht der Compiler davon aus, dass das Ergebnis auch eine Integer-Zahl sein muss (10/3 = 3.333 => 3).
Im zweiten Beispiel kommt noch ein weiteres Aspekt hinzu: ab 0.5 nach dem Komma, wird gerundet (11/3 = 3.667 => 4).

Damit trotzdem das richtige Ergebnis raus kommt, muss dem Compiler mitgeteilt werden, dass eine Typeumwandlung durchgeführt werden soll. Dazu gibt es mehrere Varianten: eine aus C – Zeiten und zwei neue aus C++.

C – Variante:

// Syntax für C-Datentypcasting

(gewünschter Datentyp)Ausdruck
// ein Beispiel

int euro = 11;
int personen = 3;

 // 11 Euro auf 3 Personen teilen (float = float/int)
float euro_pro_person = (float)euro / personen;

cout<<"euro_pro_person: "<< euro_pro_person <<endl;

1. C++ – Variante:

Bei dieser Variante steht nicht der gewünschte Datentyp sondern der Ausdruck in Klammern. Der Datentyp steht vor der Klammer.

gewünschter Datentyp(Ausdruck)
// ein Beispiel

int euro = 11;
int personen = 3;

 // 11 Euro auf 3 Personen teilen (float = float/int)
float euro_pro_person = float(euro) / personen;

cout<<"euro_pro_person: "<< euro_pro_person <<endl;

2. C++ – Variante:

Diese Variante ist die neueste und die beste.

static_cast< gewünschter Datentyp >(Ausdruck)
// ein Beispiel

int euro = 11;
int personen = 3;

 // 11 Euro auf 3 Personen teilen (float = float/int)
float euro_pro_person = static_cast<float>(euro) / personen;

cout<<"euro_pro_person: "<< euro_pro_person <<endl;

Neben static_cast gibt es noch ein andere Cast-Operatoren: const_cast, dynamic_cast und reinterpret_cast. Diese werden in anderen Zusammenhängen benutzt und für uns sind sie momentan ohne Bedeutung.

Jede dieser Varianten ist gültig und jede führt zu einem richtigen Ergebnis. Doch was haben wir eigentlich gemacht? Wir haben den Zähler von int in float umgewandelt, alles andere erledigt der Compiler. Er castet den Nenner automatisch in float um, teilt den Zähler durch den Nenner und weist das Ergebnis der float-Variable euro_pro_person zu.

Man sollte beachten, dass beim Typecasting nur der Inhalt der Variable konvertiert wird und das noch temporärer, d.h. dass der Datentype und die Variable nicht verändert werden. So wird in unserem Fall die Variable euro in keiner Weise verändert.

Als einen weiteren Punkt möchte ich erwähnen, dass Typecasts ziemlich langsam sind, deswegen sollte man sie so weit wie möglich vermeiden. In unserem Falle hätten wir einfach die Variable euro als float deklarieren sollen, was auch logischer wäre.

Das Datentypecasting spielt eine große Rolle beim Arbeiten mit Zeigern, insbesondere mit den void – Zeigern, aber dazu später mehr.

Übungsaufgaben

  1. Wie funktioniert das implizite Typecasting?
  2. Weshalb braucht man das explizite Type-Casting?
  3. Nennen Sie eine explizite Type-Casting Möglichkeit
  4. Was ist der Nachteil von Type-Casts?

3 Gedanken zu “C++ Teil 4 – Datentypecasting”

  1. Hi Maxim!

    Ich habe den Verdacht, daß hier etwas nicht stimmt:

    int euro = 11;
    int personen = 3;

    // 11 Euro auf 3 Personen teilen (float = int/int)
    float euro_pro_person = euro / personen;

    cout<<"euro_pro_person: "<< euro_pro_person < 3).
    Im zweiten Beispiel kommt noch ein weiteres Aspekt hinzu: ab 0.5 nach dem Komma, wird gerundet (11/3 = 3.667 => 4).

    Ich habe es nicht geschafft dort irgendwie zu einer 4 zu kommen und wenn ich deinen Quelltext ins C++-Programm kopiere und ausführe erscheint auch eine 3!!

    Bitte schau mal ob das so stimmt.
    Wenn ja, bitte schreib mal was das los sein könnte.

    Gruß
    Johannes

  2. Hallo Johannes.
    Ich habe das Beispiel noch mal ausgeführt und du hast Recht. Ich habe auch noch mal nachgelesen, C++ rundet anscheinend immer ab. Wahrscheinlich war es ein Compiler-Fehlverhalten, da ich die Beispiele immer teste und es mir damals sicherlich aufgefallen wäre.
    Hast du es mal mit VS2008 oder alten DevC++ probiert?
    Ich muss mal bei Gelegenheit das Tutorial überarbeiten.
    Danke
    Gruß

  3. Ich benutze ein neueres DevC++, sowie CodeBlocks und auch Emacs kombiniert mit G++.
    Eine überarbeitete Tut-Fassung wäre nicht schlecht, weil mir noch an anderen Stellen ein paar Unstimmigkeiten aufgefallen sind. Ich kann das aber mangels Erfahrung oft nicht richtig beurteilen^^.

Schreibe einen Kommentar