Datentyp-umwandlung
Literale sind:Bezeichner mit einem festen Wert wie z.B:
237 (dezimale Angabe)034 (oktale Angabe)0x51f (hexadezimale
Angabe)3.14 (Fließkommazahl)
'x' (Zeichen)"abc" (Zeichenkette)
Literale sind dem Compiler bekannt und müssen nicht - wie Variable - deklariert (angemeldet) werden.
Welchen Datentyp hat ein Literal ?
Welchen Datentyp hat z.B. eine Ganzzahl wie
4 000 000 000 ?Kann diese z.B. den
Datentyp int annehmen ?
Dazu muss man sich fragen :1) Wie viele Bytes werden für int (in MS VC++) reserviert ?2) Welchen Zahlenbereich umfasst der Datentyp int (in MS VC++) ?
... und stellt dann fest:4 Bytes reserviert MS VC++ für int. Man kann also 232 = 4294967296 Zahlen abspeichern. Da int auch negative Zahlen umfasst, geht der Zahlenbereich von: -2147483648...2147483647
Kann also die Ganzzahl 4 000 000 000 mit dem Datentyp int abgespeichert werden ?
Nein, denn int umfasst nur den Zahlenbereich von: -2147483648...2147483647
Also wird Ganzzahlen zwischen: -2147483648...2147483647der Datentyp int zugeordnet und Ganzzahlen zwischen 2147483648...4294967295der Datentyp unsigned int zugeordnet
Ganzzahlen werden also - abhängig vom Wert - folgende Datentypen zugeordnet:
dezimale Ganzzahl:int
unsigned int
long
z.B: 1234
z.B: 4 000 000 000
unsigned long
Siehe Hilfe in MS VC++
Einer Fließkommazahl wird der folgende Datentyp
zugeordnet:
double
Beispiel:
...int i,j;double d;i=2*3;d=1.9*2.1;j=4/5;...
Welchen Datentyp hat 2*3, 1.9*2.1 und 4/5 ?
Merke:
int + int = intint - int = intint * int = int
int / int = int
float + float = floatfloat - float = floatfloat * float = float float / float = float
double + double = doubledouble - double = doubledouble * double = double double / double = double
Weil z.B. 3/10 keine ganze Zahl (integer)
ergibt.
Welche der Regeln widerspricht unserer Alltagsmathematik?
Welche Datentypen haben also die folgenden Ergebnisse:
double
1.9 * 2.1
double
double
Ergebnis: 3.99
double * double = double
double
3.0 / 2.0
double
double
Ergebnis: 1.5
double /double = double
integer
2 * 3
integer
integer
Ergebnis: 6
integer * integer = integer
integer
8 / 5
integer
integer
Ergebnis: Der Nachkommateil von 8/5 = 1.6 (also 0.6) wird entfernt. Also ist das Ergebnis: 1
integer / integer = integer
Problem:Verschiedene Datentypen in
einem Ausdruck
Welchen Datentyp hat der gesamte Ausdruck ?
Beispiel:
...int i;double d;double erg;i=2;d=3.14;erg=i*d;...
Welchen Datentyp hat i*d ?
Antwort:Gemischte Datentypen
werden nicht akzeptiert !!!
Deshalb muss vorher eine Datentyp-Umwandlung
gemacht werden !!!
Dazu gibt es zwei Möglichkeiten:
Implizite Typumwandlung (macht der Compiler selbst, ohne Zutun des Programmierers)
Explizite Typumwandlungmit dem cast-Operator (muss der Programmierer machen)
und
Implizite Typumwandlung:wandelt alle "kleineren" Datentypen in die "grösseren" um.
Tabelle Typumwandlung:
long doubledoublefloatunsigned longlongunsigned intintchar signed
charunsigned
charshort unsigned
short
grös
ser
Diese Datentypen werden direkt in integer umgewandelt:
... char c1 = 64; char c2 = 64; int i = c1 * c2; ...
Welcher Wert wird in i gespeichert ? Was geschieht
im Einzelnen ?
Laut der "Tabelle Typumwandlung" wird der Wert von c1 und c2 sofort in int umgewandelt, nicht erst das Ergebnis c1*c2
Der Wert von c1 * c2, also 4096 wird dann in i gespeichert.
Beispiel:
...int i;double d;double erg;i=2;d=3.14;erg=i*d;...
Welchen Datentyp hat i*d ?
//double: erg=6.28
wird umgewandelt in double, also: 2.0 double,
also: 3.14
double * double = double
Explizite Typumwandlung(mit cast-Operator):
Wandelt mit dem cast-Operator ( ) den Datentyp um.
Beispiel:
...int i;double d;double erg;i=2;d=3.14;erg=d*(double)i;...
double, also: 2.0
double, also 3.14
integer, also: 2
double * double = double
Beispiel:
...int i;double d;int erg ;i=2;d=3.14;erg=i*(int)d;...
Warum gibt es ein Problem ?Es entsteht ein Datenverlust durch (int) d
double, also: 3.14
integer, also: 3
Bei einem möglichen Datenverlust bringt der MS VC++ Compiler eine
Warnung, keine Fehlermeldung.
Der Compiler prüft dabei nicht nach, ob es tatsächlich einen
Datenverlust gibt, sondern nur, ob ein "größerer Datentyp" in einem "kleineren Datentyp"
abgespeichert werden soll und deshalb der dafür vorgesehene Speicherplatz nicht ausreicht.
ACHTUNG:Es ist nicht normiert, wann der Compiler eine Warnung
bringen muss.
Problem:
Bei der Datentypumwandlung eines größeren Datentyps in einen kleineren Datentyp kann (muß aber nicht) ein Informationsverlust entstehen.
Konkretes Beispiel für einen Informationsverlust
int main(){ int i; char z; i = 321; z = (char) i; printf("z=%c",z); }
aus wieviel Bytes besteht i ?
4 Bytes
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1
Wie sieht die Dualdarstellung von
i aus ?
welche Bytes werden abgeschnitten ?
die Höherwertigen
aus wieviel Bytes besteht z ?
1 Byte
int main(){ int i; char z; i = 321; z = (char) i; printf("z=%c",z); }
0 1 0 0 0 0 0 1
Welches Zeichen wird ausgegeben ? (siehe ASCII-Tabelle)
A01000001
entspricht dezimal 65
int main(){ int i; char z; i = 321; z = i; printf("z=%c",z); }
Was ist hier anders im Vergleich zum letzten Programm ?
Der explizite cast-Operator (char) fehlt.
Der Wert von i, nämlich 321 ist zu groß, als dass er in der Variable z
gespeichert werden kann.
Deshalb wird i implizit in den Datentyp char umgewandelt (Compiler bringt Warnung).
Allgemein gilt:Soll bei einer Zuweisung ein größerer Wert in einer Variablen
gespeichert werden, als diese aufnehmen kann, so wird vorher eine implizite Typumwandlung gemacht.
int main(){ double d; int i=2; d=i; return 0;}
Was ist hier anders im Vergleich zum letzten Programm ?
Der Wert von i soll in einem "grösseren" Datentyp abgespeichert werden.
Deshalb wird i implizit in den grösseren Datentyp double umgewandelt.
Allgemein gilt:Soll bei einer Zuweisung ein kleinerer Wert in einer Variablen eines
"grösseren" Datentyps gespeichert werden, so wird vorher eine implizite Typumwandlung in den grösseren Datentyp gemacht.
Noch ein Beispiel:
int main(){ float f; f = 2.123456789012345;
return 0;}
Warnung: double ---> floatErgebnis: f1 = 2.12346
doublefloat
Es findet also ein tatsächlicher Datenverlust statt, weil double mehr Nachkommastellen speichert als float.
Grosses Beispiel:
int main(){ float f1, f2; double d1, d2; int i1, i2; f1 = 2.3; i1 = 4; i2 = (float)f1; d1 = 3.14; f1 = 6-1/20*f1; f2 = 6-f1/20; // weiter ...
f2 = 6-((float)1/(float)20)*f1; f2 = 6-(1/(float)20)*f1; f2 = 6-(1/20)*f1; f2 = 6-(1.0/20.0)*f1; f2 = 6-0.05*f1; f2 = 0.05*f1; d2 = 6-(1.0/20.0)*f1; d2 = 6-0.05*f1; d2 = 0.05*f1; d2 = 3/5; d2 = 3.0/5.0; }
d2 = i1 * 2.718;}
f1 = 2.3;
doublefloat
Warnung: double ---> floatErgebnis: f1 = 2.3
i1 = 4;
intint
okay:Ergebnis: i1 = 4
i2 = (float)f1;
float
int
Warnung: float ---> inti2 = 2
cast
float
d1 = 3.14;
doubledouble
okay:Ergebnis: d1 = 3.14
f1 = 6 – 1 / 20 * f1;
implizit:(float)0
okay:Ergebnis: f1 = 6
float (konkret 2.3)
intint
implizit:(float)6
int / int = int also:
1 / 20 = 0
float
int
float
float
Punkt vor Strich
f2 = 6 – f1 / 20;
okay:Ergebnis: f2 = 5.7
float, konkret 6 int
implizit:(float)20
float / int deshalb:
float / (float)int = float, also: 6.0 / 20.0 = 0.3
intfloat
int - floatdeshalb:
(float)int – float = float, also: 6.0 – 0.3 = 5.7
implizit:(float)6
f2 = 6-((float)1/(float)20)*f1;
6.0
float / float = float also:
1.0 / 20.0 = 0.05
float
float * float = float also:
0.05 * 6.0 = 0.3
int
implizit:(float)6
float - float = float also:
6.0 – 0.3 = 5.7
float cast cast
okay:Ergebnis: f2 = 5.7
f2 = 6-(1/(float)20)*f1;
6.0
int / floatdeshalb:
(float)int / float = float
float
float * float = float also:
0.05 * 6.0 = 0.3
int
implizit:(float)6
float - float = float also:
6.0 – 0.3 = 5.7
float cast
okay:Ergebnis: f2 = 5.7
f2 = 6-(1/20)*f1;
6.0
int / int = int, also: 1 / 20 = 0
float - float = float also:
6.0 - 0.0 = 6.0
int
float * float = float also:
0.0 * 6.0 = 0.0
float
okay:Ergebnis: f2 = 6.0
int float
implizit:(float)0
int
implizit:(float)6
f2 = 6-(1.0/20.0)*f1;
6.0
double / double = double, also:
1.0 / 20.0 = 0.05
double - double = double also:
6.0 - 0.3 = 5.7
double * double = double also: 0.05 * 6.0 = 0.3
float
Warnung: double --->float Ergebnis: f2 = 5.7
int float
implizit:(double)6
double double
implizit:(double)6
f2 = 6 - 0.05 * f1;
6.0
double * floatdeshalb:
double * (double)float = double
double - double = double also:
6.0 - 0.3 = 5.7
double * double = double also: 0.05 * 6.0 = 0.3
float
Warnung: double --->float Ergebnis: f2 = 5.7
int float
implizit:(double)6
implizit:(double)6
double
f2 = 0.05*f1;
6.0
double * floatdeshalb:
double * (double)float = double, also:0.05 * 6.0 = 0.3
float
Warnung: double --->float Ergebnis: f2 = 0.3
double
implizit:(double)6
float
d2 = 6-(1.0/20.0)*f1;
6.0
double / double = double, also:
1.0 / 20.0 = 0.05
double - double = double also:
6.0 - 0.3 = 5.7
double * double = double also: 0.05 * 6.0 = 0.3
double
okay:Ergebnis: d2 = 5.7
int float
implizit:(double)6
double double
implizit:(double)6
d2 = 6 - 0.05 * f1;
6.0
double * floatdeshalb:
double * (double)float = double
double - double = double also:
6.0 - 0.3 = 5.7
double * double = double also: 0.05 * 6.0 = 0.3
double
okay: Ergebnis: d2 = 5.7
int float
implizit:(double)6
implizit:(double)6
double
d2 = 0.05 * f1;
6.0
double * floatdeshalb:
double * (double)float = double, also:0.05 * 6.0 = 0.3
double
okay: Ergebnis: d2 = 0.3
double
implizit:(double)6
float
d2 = 3 / 5;
int / int = int, also:
3 / 5 = 0
double
okay: Ergebnis: d2 = 0.0
int int
d2 = 3.0 / 5.0;
double / double = double, also:
3.0 / 5.0 = 0.6
double
okay: Ergebnis: d2 = 0.6
double double
d2 = i1 * 2.718;
double
okay: Ergebnis: d2 = 10.872
int double4
int * doubledeshalb:
(double) int * double = double, also:
4.0 * 2.718 = 10.872
Zusammenfassung
int main(){ float f1, f2; double d1, d2; int i1, i2; f1 = 2.3; i1 = 4; i2 = (float)f1; d1 = 3.14; f1 = 6-1/20*f1; f2 = 6-f1/20; // weiter ...
//Warnung: double ---> float
//Warnung: float ---> int
// Ergebnis: f1 = 6 // Ergebnis: f2 = 5,7
f2 = 6-((float)1/(float)20)*f1; f2 = 6-(1/20)*f1; f2 = 6-(1.0/20.0)*f1; f2 = 6-0.05*f1; f2 = 0.05*f1; d2 = 6-(1.0/20.0)*f1; d2 = 6-0.05*f1; d2 = 0.05*f1; d2 = 3/5; d2 = 3.0/5.0; d2 = i1 * 2.718;
// Warnung: double ---> float
// Ergebnis: d2=0.6
// Ergebnis: d2 = 0
//Warnung: double ---> float
// Warnung: double ---> float
// Ergebnis: f2 = 6
// Ergebnis: d2 =5,7
// Ergebnis: d2 =5,7
// Ergebnis: d2 =0,3
// Ergebnis: d2 =10,872