|
feld[i*3+j-7] = feld[i*3+j-7] + 10; /* normal */
feld[i*3+j-7] += 10; /* abgekürzt */
Zusammengesetzte Zuweisungsoperatoren:
+= | x += ausdr | <-- | x = x + ausdr |
-= | x -= ausdr | <-- | x = x - ausdr |
*= | x *= ausdr | <-- | x = x * ausdr |
/= | x /= ausdr | <-- | x = x / ausdr |
%= | x %= ausdr | <-- | x = x % ausdr |
&= | x &= ausdr | <-- | x = x & ausdr |
|= | x |= ausdr | <-- | x = x | ausdr |
^= | x ^= ausdr | <-- | x = x ^ ausdr |
<<= | x <<= ausdr | <-- | x = x << ausdr |
= | x >>= ausdr | <-- | x = x >> ausdr |
Implizite Typumwandlung
Datentypwandlungen sind immer dann notwenig, wenn zwei Operanden in einem
Ausdruck verschiedene Typen haben. Die Datentypwandlungen werden soweit notwendig
implizit durchgeführt. Es gelten folgende Regeln:
- char wird bei Bewertungen immer in int gewandelt,
dadurch sind int und char beliebig mischbar.
Allerdings kann die char-int Wandlung rechnerabhängig
sein, char kann auf die Zahlenwerte -128 bis +127 oder
0 bis +255 abgebildet sein, die "normalen" Zeichen liegen
aber immer im positeven Bereich.
Die char-int Wandlung ist vor allem bei der Abfrage eines
eingelesenen Zeichens auf EOF wichtig (Eingelesen werden
immer int Werte, die dann aber einfach char Werten
zugewiesen werden können).
- die Wandlung von int nach long erfolgt durch Vorzeichenerweiterung
(bei signed) oder Voranstellen von Nullen (unsigned), bei der
umgekehrten Wandlung werden die höchstwertigen Bits einfach
abgeschnitten.
- float wird bei Bewertungen immer in double gewandelt,
alle Rechnungen erfolgen daher mit derselben großen Genauigkeit.
Die Wandlung von int nach float ist wohldefiniert,
die umgekehrte Richtung kann rechnerabhängig sein, insbesondere
bei negativen Gleitkommazahlen.
Zusammenfassung:
Variable |
= |
Variable |
durchgeführte Typumwandlung |
int int |
<-- <-- |
float double |
Weglassen des gebrochenen Anteils |
int char char |
<-- <-- <-- |
long int short |
Weglassen der höherwertigen Bits |
float |
<-- |
double |
Runden oder Abschneiden (implementierungsabhängig) |
float double |
<-- <-- |
long, int, short,char |
Wenn keine exakte Darstellung möglich
Runden oder Abschneiden (implementierungsabhängig) |
Bei Parameterübergabe an Funktionen erfolgt die Umwandlung des Typs des
aktuellen Parameters in den Typ des formalen Parameters nach obigen Regeln.
Den genauen Ablauf der Wandlungen bei der Auswertung eines Ausdrucks
oder einer Zuweisung beschreiben folgende Regeln (übliche
arithmetische Umwandlungen):
- Zuerst werden char oder short Operanden in int
Werte und float Operanden in double Werte umgewandelt.
- Hat jetzt ein Operand den Typ double, so wird der andere
ebenfalls in double gewandelt und das Resultat ist auch
double.
- Ist stattdesssen einer der Operanden long, so wird der
andere auch in long gewandelt und das Resultat ist auch
long.
- Ist andernfalls einer der Operanden unsigned, so wird auch
der andere in unsigned gewandelt und das Resultat ist ebenfalls
unsigned.
- Liegt keiner dieser Fälle vor, so handelt es sich um int-Werte,
diesen Typ hat dann natürlich auch das Resultat.
Beispiel:
Vorsicht:
- Division zweier int ergibt wieder int, also den
Ganzzahlanteil des mathematischen Wertes.
- Bei Umwandlung von höherwertigem
zu niederwertigem Datentyp ist Informationsverlust möglich!
- Achtung bei Vergleich von signed und unsigned Typen!
Beispielsweise könnte WAHR sein: -1 > 1U
Explizite Typumwandlung (type cast)
In manchen Fällen ist es erforderlich die Typkonversion gezielt vorzunehmen.
Das sieht man am besten mit einem Beispiel:
int j = 12, k = 18;
float f;
...
f = k/j; /* in f steht 1.0 */
...
Beide Operanden der Division k/j sind int-Variablen. Also ist
auch das Ergebnis der Division vom Typ int (18/12 = 1 Rest 6). Die Zuweisung
erfolgt nach der Division. Mit der impliziten Typkonversion erfolgt dann die Expansion
von 1 zu 1.0. Sollte das "echte" Ergebnis gewünscht werden, so wird dies durch eine explizite Typumwandlung möglich.
Die explizite Typumwandlung (type cast) erfolgt mittels des Cast-Operators, der unmittelbar vor den Ausdruck zu setzen ist, dessen Typ konvertiert werden soll. Der Cast-Operator ist
ganz einfach eine in Klammern gesetzte Typangabe. Obiges Beispiel wird geändert zu:
int j = 12, k = 18;
float f;
...
f = (float)k/j;
...
Die Variable k wird nun zu einer float-Variablen
typkonvertiert (Neudeutsch: "gecastet"). Bei der Division von float
durch intwird j implizit auf float
typkonvertiert und so ergibt sich das korrekte Ergebnis 1.5.
Beispiel: Wandelt die nächsten x Ziffern aus dem String s in eine Integerzahl
atoi(char s[])
{
int i,n;
n=0;
for (i=0; s[i]>='0' && s[i]<='9'; i++)
n = 10*n + s[i]-'0';
return (n);
}
Beispiel: Wie atoi, aber für Hexadezimalzahlen.
htoi(char s[])
{
int i,n;
n=0;
for (i=0; ; i++)
if (s[i] >= '0' && s[i] <= '9')
n = 16*n + s[i]-'0';
else if (s[i] >= 'A' && s[i] <= 'F')
n = 16*n + s[i]-'A'+10;
else if (s[i] >= 'a' && s[i] <= 'f')
n = 16*n + s[i]-'a'+10;
else
break;
return (n);
}
|
|
|