Datentyp- umwandlung. Literale sind: Bezeichner mit einem festen Wert wie z.B:

Preview:

Citation preview

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

Recommended