Typumwandlung
Als Typumwandlung (englisch type conversion oder type casting, kurz cast) wird in der Informatik die Umwandlung eines Datums von einem Datentyp in einen anderen bezeichnet. Dadurch werden Typverletzungen vermieden, die durch mangelnde Zuweisungskompatibilität entstehen.
Hierbei unterscheidet man zwischen
- expliziter und impliziter Typumwandlung;
- werterhaltender und verlustbehafteter Typumwandlung;
- benutzerdefinierter und vordefinierter (“built-in”) Typumwandlung.
Bei der expliziten Typumwandlung wird die Typumwandlung im Programmcode ausdrücklich hingeschrieben. Je nach Typisierung der verwendeten Programmiersprache kann das Fehlen der expliziten Angabe der Typumwandlung einen Laufzeit- oder Compilezeit-Fehler zur Folge haben. Im Unterschied dazu erscheinen implizite Typumwandlungen nicht im Quelltext. Sie erfolgen entweder nach Vorschriften, die durch die Programmiersprache vorgegeben sind, oder gemäß einem vom Programmierer an einer anderen Stelle im Quelltext festgelegten Verfahren.
Eine Typumwandlung ist werterhaltend, wenn alle im Ausgangstyp darstellbaren Werte auch im Zieltyp darstellbar sind, so dass sich der Wert, also das umgewandelte Datum, auf keinen Fall ändert. Anderenfalls nennt man sie verlustbehaftet. Implizite Typumwandlungen können eine Fehlerquelle sein, indem versehentlich eine verlustbehaftete Umwandlung verursacht wird. Deshalb erlauben viele Programmiersprachen eine implizite Typumwandlung nur dann, wenn sie werterhaltend ist.
Typerweiterung und Typeinschränkung
BearbeitenDa unterschiedliche Datentypen oftmals unterschiedliche Wertebereiche haben, können bei der Typumwandlung Typerweiterungen, also Vergrößerungen des Wertebereichs, oder Typeinschränkung, also Verkleinerungen des Wertebereichs, vorkommen.
Wird beispielsweise ein Integer mit einer Größe von 16 Bit in einen 32 Bit großen Integer umgewandelt, handelt es sich um eine Typerweiterung. Im umgekehrten Fall wäre dies eine Typeinschränkung.
Beispiele
BearbeitenJava
Bearbeiten// Explizite Typumwandlung
int i = 100;
byte b = (byte) i;
// Implizite Typumwandlung
int j = 12;
double d = j;
// Bei Zeichenketten wird beim expliziten umwandeln String.valueOf(x)
// bzw. bei Objekten x.toString() aufgerufen:
int i = 164;
String str = String.valueOf(i);
// Implizite Typumwandlung bei Zeichenketten
int i = 164;
String str = "" + i;
// Anwendungsbeispiel der expliziten Typumwandlung:
int g = 9;
int n = 2;
double e = g/n; // e ist nicht 4.5, sondern 4.0, da eine Ganzzahldivison erfolgt, deren Ergebnis 4 ist.
// Anschließend findet erst die Typumwandlung auf double statt und e weist den Wert 4.0 auf
// Um dieses Verhalten zu umgehen, kann man eine explizite Typumwandlung benutzen:
double y = g / (double)n;
C#
BearbeitenGeraet geraet = new Computer();
Bildschirm bildschirm = (Bildschirm) geraet; // Wenn (geraet is Bildschirm), stat.type(geraet) is Bildschirm, sonst wird eine Exception geworfen
bildschirm = geraet as Bildschirm; // Wenn (geraet is Bildschirm), bildschirm = (Bildschirm) geraet, sonst bildschirm = null
geraet = null;
bildschirm = geraet as Bildschirm; // bildschirm == null
C++
BearbeitenGeraet* geraet = new Computer;
Bildschirm* bildschirm = static_cast<Bildschirm*>(geraet); // Kompiliert nur, wenn entweder Geraet or Bildschirm von der anderen oder derselben Klasse abgeleitet ist
bildschirm = dynamic_cast<Bildschirm*>(geraet); // Wenn (geraet is Bildschirm), dann bildschirm = (Bildschirm*) geraet, sonst bildschirm = nullptr
Bildschirm& bildschirmR = static_cast<Bildschirm&>(*geraet); // Wie oben, aber eine Exception wird geworfen, wenn ein nullptr zurückgegeben wird
geraet = nullptr;
bildschirm = dynamic_cast<Bildschirm*>(geraet); // bildschirm == nullptr
delete geraet; // gibt die Ressourcen frei
Implizite Typumwandlung als Fehlerquelle:
int main() {
int a = -4;
unsigned b = 5;
if (a > b) cout << "Fehler" << endl;
}
Hier wird a implizit von int nach unsigned gewandelt, und da im Zieltyp keine negativen Zahlen darstellbar sind, ändert sich der Wert. Das Resultat ist laut den Regeln der Ganzzahlumwandlung kongruent zu -4 modulo der Zahl der im vorzeichenlosen Zieltyp darstellbaren Werte, also , wenn unsigned 32 Bit lang ist.