4. Grundlagen von Programmiersprachen

Werbung
4. Grundlagen von Programmiersprachen
- Einfache Typen, Ausdrücke, Typanpassung 4.1
4.2
4.3
4.4
Datentypen
Ausdrücke
Typanpassung
Vereinbarung von Variablen
und deren Typen
4.1 Datentypen (1)
z
Programmiersprache heißt getypt (strong typing),
wenn
- jede Variable
- jedes Literal
- jeder Ausdruck
z
z
int myVar;
"Zeichenkette"
220/2
Java
einen (Daten-)typ besitzt.
Zu jedem Typ T: Menge von Operatoren, die auf
Werten von T definiert sind
Statisch getypte Sprache (static typing):
Korrekter Typ ("darf Operator angewendet werden?") wird
vor Ausführung des Programms geprüft.
hs / fub - alp2-04 2
Einfache Datentypen
ganze Zahlen
Zahlen
1. Elementare (primitive) DT
int, byte,
long
Zeichen char
Wahrheitswerte
boolean
Aufzählungtypen
2. Benutzerdefinierte DT
public enum Weekend {SA,SU}
(seit Java 1.5)
Bereiche
[10..20]
(nicht in Java)
Weitere (zusammengesetzte) Typen:
- Felder
Aus Teilen zusammengesetzt,
die einzeln manipuliert werden
- Klassen
können. Oft rekursives Konstruktionsprinzip
!
r
e
t
ä
p
S
hs / fub - alp2-04 3
Wertebereiche von Zahldatentypen in Java
public class BoundsOfNumbers {
public static void main (String[] args) {
System.out.println(" byte=["+Byte.MIN_VALUE+".."+Byte.MAX_VALUE+"]");
System.out.println(" short=["+Short.MIN_VALUE+".."+Short.MAX_VALUE+"]");
System.out.println("
int=["+Integer.MIN_VALUE+".."+Integer.MAX_VALUE+"]");
System.out.println(" long=["+Long.MIN_VALUE+".."+Long.MAX_VALUE+"]");
System.out.println(" float=["+Float.MIN_VALUE+".."+Float.MAX_VALUE+"]");
System.out.println("double=["+Double.MIN_VALUE+".."+Double.MAX_VALUE+"]");
System.out.println("double=["+Double.NEGATIVE_INFINITY+".."
+Double.POSITIVE_INFINITY+"]");
System.out.println("Infinity+1: " + (Double.MAX_VALUE+1.0));
System.out.println(" Maxint+1 ="+(Integer.MAX_VALUE+1));
}
byte=[-128..127]
short=[-32768..32767]
int=[-2147483648..2147483647]
long=[-9223372036854775808..9223372036854775807]
float=[1.4E-45..3.4028235E38]
double=[4.9E-324..1.7976931348623157E308]
double=[-Infinity..Infinity]
Infinity+1: 1.7976931348623157E308
Maxint+1 =-2147483648
hs / fub - alp2-04 4
Charakterisierung von Datentypen
- Repräsentation von Werten ?
Beispiel: 16-Bit-Unicode Zeichendarstellung in Java
Nicht sinnvoll! Implementierungsabhängig.
- Operatoren, die auf Werte des Typs angewendet
werden können
Beispiel: Addition (+), Multiplikation (*), Subtraktion (-) auf allen
numerischen Datentypen
hs / fub - alp2-04 5
Allen Datentypen gemeinsame Operationen:
(1) Vergleichsoperatoren:
== Gleichheit
a == b hat Wert true, wenn a=b, sonst false
Ergebnis: Bool'scher Wert
!= Ungleichheit
a != b ... wenn a≠b
Vergleiche Haskell: == und /=
Warum in Haskell Vergleichsoperatoren nicht für alle Typen
definiert?
class Eq
hs / fub - alp2-04 6
(2) Zuweisungsoperator
<variable> = <Ausdruck>
ist [in Java] ein Ausdruck, der einen Wert hat und
als Nebeneffekt diesen Wert der <variable> zuweist.
int i=2,j=3,m;
System.out.println("i+j: "+ (m = i+j));
(ternärer Operator) der bedingungsabhäng(3) wenn –
dann – sonst
ig einen
von zwei Werten liefert. Java-Syntax:
<bedingung> ? <wert1> : <wert2>
i > 0 ? i : -i
Nicht mit Fallunterscheidung verwechseln:
if <bed> {Anweisung1} else {Anweisung2};
hs / fub - alp2-04 7
Datentypen und Operationen [in Java]
Wahrheitswerte boolean
Literale: true, false
Operationen:
!
&, &=
|, |=
&&
||
Negation
Konjunktion, mit Zuweisung an ersten Operanden
Disjunktion, mit Zuweisung an ersten Operanden
Konjunktion, nichtstrikt im 2.Operanden
Disjunktion, nichtstrikt im 2. Operanden
boolean b1 = true, b2 = true, b3= false;
b1 &= b3;
System.out.println("b1="+b1);
b2 = b1 &&(0/0==0);
System.out.println("b2="+b2);
b1=false
b2=false
hs / fub - alp2-04 8
Zeichen char
Literale: 'a,'b',...,
'\f',...,\u0000
Achtung: Unbedingt
Details zu Datentypen
in Java aus (Hand-) Buch
entnehmen.
Repräsentiert durch 16 Bit Unicode
Operationen: ++, --, +, liefert das Nachfolge-, Vorgängerzeichen
char c = 'c'
++c == 'd'
auch als postfix:
char x = c++;
x=='d' nicht 'e' (wegen c=='d')
char x, y='c';
System.out.println("y="+(++y)+ ", x=" +(x=y++)+ ", y=" +y);
y=d, x=d, y=e
hs / fub - alp2-04 9
Zahlen
(1) Ganze Zahlen
int 32 Bits Zweierkomplement
int=[-2147483648..2147483647]
Dezimale, oktale (0 und Ziffern 0-7) und
hexadezimale (0x und Ziffern 0-9,a,b,c,d,e,f) Darstellung
Beachte 55 ≠ 055 ≠ 0x55
Weitere Repräsentationen:
long 64 Bits
Werte: <ziffernfolge>L 12345678L
(angehängtes L oder l; besser: L )
short
byte
16 Bits
8 Bits, [-128 .. 127], Zweierkomplement!
Initialwert: 0
hs / fub - alp2-04 10
Operationen auf ganzen Zahlen
unär: +
-
(Vorgänger, Nachfolger)
binär: + - * (ohne Überlaufkontrolle)
/ (ganzzahlig)
int i = 123456789;
% mit:
System.out.println("
++
--
a % b =a-
a
⎣b⎦
*b
i="+(i*100));
i=-539222988
Sonstige Operationen
&
+=
|
bitweise und, oder, exklusives oder
^
-=
*=
/=
%=
&=
|=
^=
Operation mit Zuweisung an linken Operanden
<
<=
>
>=
Vergleichsoperatoren
hs / fub - alp2-04 11
(2) Gebrochene Zahlen
double
float
64-Bit Gleitpunktformat für rationale Zahlen
32-Bit Gleitpunktformat
(gemäß IEEE 754 Spezifikation)
Werte:
Dezimalzahlen mit/ohne Dezimalpunkt,
mit/ohne angehängten Exponenten
E<ganze Zahl>
oder e<ganze Zahl>
(= e)
Float-Werte müssen durch angehängtes
n gekennzeichnet sein.
27182818E-7
27182818E-7f
Weitere gemäß IEEE: POSITIVE_INFINITY
NEGATIVE_INFINITY
NaN (not a number, z.B. 0/0)
Initialwert: 0.0 bzw. 0.0F
hs / fub - alp2-04 12
Operationen auf gebrochenen Zahlen:
wie auf ganzen Zahlen, außer Bit-Operationen
z.B. e%2: 0.8182819
Vorsicht beim Rechnen mit Gleitkommazahlen!
double euros1 = 0.01 + 0.05 + 0.10 + 0.25;
double euros2 = 0.25 + 0.10 + 0.05 + 0.01;
System.out.println("Euro1="+euros1);
System.out.println("Euros="+euros2);
Euro1=0.41000000000000003
Euros=0.41
hs / fub - alp2-04 13
… Fehler bei Gleitkommaoperationen
e*55/55-e : 0.0
e-55+55-e != 0: true
⇒ nie auf (Un-)Gleichheit testen
Assoziativität?
(0.01f + 12345678)-12345678 :0.0
0.01f + (12345678-12345678) :0.1
Gründe: unvermeidliche Rundungsfehler,
Binär statt Dezimaldarstellung.
z.B. unendliche Dezimal- / Binärbrüche
hs / fub - alp2-04 14
Dezimale Datentypen (nicht in Java)
- Konversionen vermeiden
- Nützlich / wichtig in Finanz- und
Wirtschaftsanwendungen
- Heute fast nur in Software
- Sprachen: C++, COBOL, PL/1, SQL (Datenbanksprache)
- Unterstützung durch Dezimalarithmetikeinheit möglich.
Vorzeichen
Prinzip:
Bytegrenze
Pro Halbbyte eine dezimale Ziffer (mit Pseudotretraden),
Dezimalpunkt per Software.
hs / fub - alp2-04 15
Datentyp ist definiert durch die auf Werten dieses Typs
erlaubten Operationen – nicht durch seine
Repräsentation (Implementierung).
Verschiedene DT können gemeinsame Operationen
besitzen, +, *, - auf allen Zahltypen definiert, aber
völlig verscheiden implementiert.
Trennung von Eigenschaften ("Spezifikation") und
Realisierung wichtiges Grundprinzip der Informatik.
⇒ Abstrakte Datentypen … später
hs / fub - alp2-04 16
Die einfachsten nichtprimitiven Typen: enum, array
Aufzählungstypen (enumeration type)
Endliche Menge von Konstanten (Werten), deren Bezeichner
(Namen)vom Programmierer in einer Typedefinition festgelegt
werden.
Java: seit 1.5
public enum Obst {APFEL,BIRNE,PFLAUME}
Achtung: enum Typen gibt es in vielen Programmiersprachen
- C, C++, Modula-2, Delphi, Haskell (algebraische Typen!),
Ada … - die Semantik ist jedoch sehr unterschiedlich.
Im einfachsten Fall: Verwendung zu Dokumentationszwecken
hs / fub - alp2-04 17
Datentyp Feld (array)
Repräsentiert eine Folge fester Länge von Variablen
des gleichen Datentyps
<typ> [] <name> = {<werte>}
int[] prim5 = {2,3,5,7,7+4}
Index der Folgenelemente: 0..(n-1) für Folge der Länge n
Zugriff auf i-tes Folgenelement: <feldname>[i]
Beispiel: prim5[0] + prim5[4] == 13
Felder gibt es in praktisch jeder Programmiersprache.
hs / fub - alp2-04 18
Grafik aus Java Tutorium (Sun)
Besonderheit von Feldern in Java
un
r
ä
l
Erk r.
te
ä
p
s
ohne Angabe der Werte ist möglich (sogar Normalfall),
das eigentliche Feld mit definierter Länge erhält man
dann erst durch eine Operation:
<typ> [] <name> = new <typ>[zahl]
char[] zeile = new char[80]
Vereinbarung <typ> [] <name>;
char[] zeile;
r
ü
f
a
gd
hs / fub - alp2-04 19
4.2 Ausdrücke (expressions)
Einfache Ausdrücke:
Literal
54 ,
Variable
i
,
'c'
tmp
Konstante
PI
Zusammengesetzte Ausdrücke
unärer
-54
-tmp
binärer
3*4.0
5*PI -3
konditionaler
tmp < 0 ? –tmp : tmp
Zuweisung
tmp = i+3
geklammerter Ausdruck (j=3+i)
Weitere Ausdrücke, z.B. Funktionsaufrufe: sin(0.342)
Jeder Ausdruck hat einen Wert.
hs / fub - alp2-04 20
Einschränkungen
z
Ausdruck muss syntaktisch korrekt sein
⇐ Syntaxanalyse des Übersetzers (Parser)
z
Ausdruck muss typkorrekt sein
⇐ Semantische Analyse
Beispiel:
a+12 ==i && c
typkorrekt, wenn a und i den Typ int haben,
c den Typ boolean.
Aber: Typanpassung möglich! s.u.
hs / fub - alp2-04 21
Bindungsstärke von
Operatoren
Wie wird a+12 == i && c
ausgewertet?
Woran erkennt Parser die
Auswertungsreihenfolge
((a+12) == i) && c ?
Explizite Klammerung immer
möglich, sonst Operatorvorrang (Bindungsstärke,
Operatorpräzedenz)
aus Java-Tutorial (Sun)
Operators
Precedence
postfix
expr++ expr--
unary
++expr --expr +expr expr ~ !
multiplicative
*/%
additive
+-
shift
<< >> >>>
relational
< > <= >=
equality
== !=
bitwise AND
&
bitwise exclusive
OR
^
bitwise inclusive OR
|
logical AND
&&
logical OR
||
ternary
?:
assignment
= += -= *= /= %= &=
^= |= <<= >>=
>>>=
fallend
hs / fub - alp2-04 22
Assoziativität von Operatoren
Für kommutative Operatoren uninteressant !?
Nein:
(0.01f + 12345678)-12345678 != 0.01f + (12345678-12345678)
Binäre (dyadische) Operatoren werden bei gleicher Bindungsstärke immer linksassoziativ geklammert und ausgewertet:
a+b-c+d ==
((a+b)-c)+d
Ausnahme: Zuweisung
a=b=c
a=(b=c)
Ternäre Operation rechtsassoziativ
a ? b : c ? d :e
== a ? b : (c? d : e)
Dringende Empfehlung: im Zweifelsfall explizit klammern!
hs / fub - alp2-04 23
Auswertung von Ausdrücken
(1) Einfache Ausdrücke: Wert den sie bezeichnen
(2) Zusammengesetzte Ausdrücke:
(a) Auswertung von links nach rechts *
(b) Beachtung der Bindungsstärke
und Klammerung
(c) Auswertung aller Operanden vor Anwendung
des Operators (eager evaluation)**
* Ausnahme: ternäre Operation (_?_:_)
** Ausnahme: nichtstrikte Operationen && , ||, (_?_:_)
hs / fub - alp2-04 24
4.3 Typanpassung
a = b + c : wann ist der Ausdruck typkorrekt?
Grundidee: in einer Zuweisung x = y muss y
einen Typ haben, der ohne Informationsverlust in
den von x überführt werden kann.
Beachte: nicht symmetrisch!
Beispiel: double x, int y;
x=y;
y=x;
// int in double wandeln 9
// Compiler meldet Fehler
hs / fub - alp2-04 25
Typverträglichkeit ( ∠ ) primitiver Typen
(1) Jeder Typ ist mit sich selbst verträglich: T ∠ T
(2) Wenn a mit b, b mit c verträglich, dann a mit c
T1 ∠ T2, T2 ∠ T3 ⇒ T1 ∠ T3
(3) In Java:
byte ∠ short ∠ int ∠ long ∠ float ∠ double
und char ∠ int
boolean ist nur mit sich selbst verträglich
Automatische Typanpassung, wenn verträglich, also
kein Informationsverlust.
hs / fub - alp2-04 26
double d = 1.0 ; int i = 077; short s = 2;
float f = 1.0F;
d = i;
// erlaubt
d = f;
// erlaubt
d = 'a'; // erlaubt! a==97.0
// f = 1.0; // Statischer Typfehler
s = 'a'; // Statischer Typfehler?! erlaubt
// Kuriosum des Typsystems,
// Wert 'passt' in Variable
f = 1234567890123L;
// erlaubt, Genauigkeitsverlust
Statische Typprüfung während der Übersetzung
hs / fub - alp2-04 27
Automatische Wertumwandlung zur Laufzeit
Liegt wird T1-Wert benötigt, aber T2-Wert liegt vor,
dann wird T2-Wert in T1-Wert umgewandelt.
doubleVar = intVar;
Repräsentation im 2er-Komplement wird in
Gleitpunktdarstellung umgewandelt.
Wenn gemäß Typverträglichkeit: widening conversion
Was geschieht mit doubleVar + intVar?
hs / fub - alp2-04 28
Typumwandlung in Ausdrücken
Kleinerer Typ wird in größeren umgewandelt,
damit Operator anwendbar ist.
Ausnahme (Java): int ist der kleinste gemeinsame Typ,
d.h. shortVar = shortVar + byteVar
liefert statischen Typfehler
("cannot convert from int to short")
shortVar + byteVar
Werte der Variablen werden in
int-Darstellung umgewandelt,
der kann nicht (ohne Weiteres)
einer short-Variablen zugewiesen
werden.
hs / fub - alp2-04 29
Explizite Typumwandlung (casting)
shortVar = intVar nicht erlaubt – intVar könnte zu großen
Wert enthalten.
intVar = floatVar nicht erlaubt – intVar muss Nachkommaanteil "abschneiden".
Cast-Ausdruck: (<type>) <ausdruck>
Type von <ausdruck> und <type> beide boolean oder
nicht boolean
D.h. keine explizite Typwandlung in / aus boolean
hs / fub - alp2-04 30
shortVar = (short)(shortVar + byteVar)
und ohne Klammer?
int intVar=1;
intVar = (int) (intVar/2.0)
automatische Typwandlung in double
wegen 2.0, cast in int.
Also besser 2 statt 2.0
Typischer Fehler:
int i = 128;
byte b = (byte) i;
Wert von b?
Denn sie wissen nicht,
was sie tun.
hs / fub - alp2-04 31
4.4 Variablen, Typen, Vereinbarung
Strenge Typisierung ⇒
Literale, Variablen, Ausdrücke besitzen einen Typ
Literale:
automatisch - ein Literal hat (kontextabhängig) genau einem
Typ
Ausdrücke:
abhängig vom Typ der Konstituenten
doubleVar + 3
Variablen:
explizit vor der ersten Nutzung vereinbaren
double doubleVar;
hs / fub - alp2-04 32
Variablenvereinbarung (declaration)
- legt Namen der Variablen
- und Typ der Variablen fest
- steht (im Prinzip) an beliebiger Stelle im Programm
… ; int i = j + k;
- darf nur einmal im "gleichen Kontext" auftreten
… ; int i = j + k;
int i = a + b;
nicht erlaubt (s. auch Abschnitt 4, Blöcke)
<type> <identifier> {,identifier}0n ;
double lowVal, highVal, meanVal;
hs / fub - alp2-04 33
Warum statische Typvereinbarung?
Festlegung, welche Werte Variable annehmen kann
⇒ Übersetzer kann Speicherplatz reservieren
⇒ Dokumentation (!)
⇒ Fehler verhindern
float val1;
double val2;
val1 = 0xffff + val1;
val1 = 0xffff + val2;
Teurer Fehler: Absturz der ersten Ariane 5 Rakete. Aus dem Report:
e) At 36.7 seconds after H0 (approx. 30 seconds after lift-off) the computer within the
back-up inertial reference system, which was working on stand-by for guidance and
attitude control, became inoperative. This was caused by an internal variable related to
the horizontal velocity of the launcher exceeding a limit which existed in the software of
this computer. (64-Bit-Zahl in 16-Bit-Zahl gewandelt)
hs / fub - alp2-04 34
Wert einer frisch deklarierten Variable v
ist vor der ersten Zuweisung v=… undefiniert(!);
double d, e;
int i;
e = 1.0;
d = e + i;
// Übersetzungsfehler
Initialisierung in Deklaration möglich
<type><identifier>[=<init>]{,identifier[=init]}0n;
double lowVal=0.0, highVal=0.0, meanVal;
Deshalb: LocalVariableDeclarationStatement
hs / fub - alp2-04 35
Konstanten
sind nicht änderbare, initialisierte Variablen:
final <type><identifier>=<init>{,identifier=init}0n;
final PI=3.14159, E=2.71828
Beachte
- <init> kann ein komplexerer Ausdruck als ein Wert sein
- Namenskonvention für Konstanten: Großbuchstaben
- Dokumentationscharakter von Konstanten
- Übersetzer garantiert (statisch) die Invarianz von Konstanten
hs / fub - alp2-04 36
Herunterladen