Es gibt sechs arithmetische Operatoren. Sie stehen für die vier
Grundrechenarten (+ - * /), die Modulofunktion (Rest nach
Division; % ) und die arithmetische Negation (das Vorzeichen).
- | Vorzeichen (Unär) |
* | Multiplikation |
/ | Division |
% | Modulofunktion |
+ | Addition |
- | Subtraktion |
Die Modulofunktion ist nicht auf float oder double
Operanden anwendbar. Die Rangfolge ist wie gewohnt: *, / und %
gleich und höher als + und -. Das Minuszeichen als unärer
Operator (Vorzeichen) hat einen höheren Vorrang als *, /
und %. Es gibt kein positeves Vorzeichen.
Beispiele für die Anwendung arithmetischer Operatoren:
int h, i=3, j=5, k=10;
float x, y=5.0, z=3.0;
h = i+j+k; /* 18 */
h = k-j-i; /* 2 */
h = i-k; /* -7 */
h = k/i; /* 3 */
h = k/i+j; /* 8 */
h = k/(i+j); /* 1 */
h = k*i+j; /* 35 */
h = k*(i+j); /* 80 */
h = k%i; /* 1 */
x = y+z; /* 8. */
x = y/z; /* 1.666... */
x = y*z; /*15. */
x = k/z; /* 3.333... */
x = k/z + y/z; /* 5. */
x = k/i + y/i; /* 4.666... */
x = k%z; /* verboten! */
Höhere Rechenoperationen wie Wurzelziehen, Potenzieren, Exponentiation,
usw. fehlen in C als Operator ganz; sie sind über Bibliotheksfunktionen
realisiert. Bei ihrer Verwendung muß in jedem Fall die Inlcude-Datei
math.h mit eingebunden werden.
Inkrement- und Dekrementoperatoren
C kennt spezielle Operatoren zum Inkrementieren und Dekrementieren. Es sind dies:
Sie sind (wie der Vorzeichenoperator -) rechts assoziativ, werden
also von rechts her zusammengefaßt. Sie können vor
oder nach ihrem Operanden stehen. Im ersten Fall
wird der Operand zunächst in- oder dekrementiert
und dann weiterverwendet, im zweiten Fall wird der
Operand erst verwendet und dann in- oder dekrementiert.
int i;
int k;
i=1;
if (++i > 1)
k = 5; /* wird durchlaufen */
if (i++ > 2)
k = 10; /* wird nicht durchlaufen */
Logische Verknüpfungen
Unter die logischen Verknüpfungen für Wahrheitswerte fallen die Operatoren:
! | logische Negation |
&& | logisches UND |
|| | logisches ODER |
Sie sind hier in ihrer Rangfolge geordnet aufgeführt, logisches
UND hat also einen höheren Vorrang als das logische ODER.
In Ausdrücken erfolgt die Abarbeitung von links nach rechts
aber nur solange, bis das Ergebnis eindeutig feststeht. Das führt
zu einer kürzeren Ausführungszeit, wenn man die häufigst
verwendete Bedingung an den Anfang einer Bedingungsabfrage stellt.
Bei Operationen, die Nebeneffekte haben können (z.B. Inkrementation),
muß man allerdings vorsichtig sein.
if (a<b && (d=(a+b)) != c) /* diese 2 Zeilen */
if ((d=(a+b)) != c && a<b) /* wirken nicht gleich */
Beispiel:
#include <stdio.h>
int main (void)
{
enum logik { false = 0, true = 1} a, b;
printf ("| a b | a&&b | a||b |\n");
printf ("|-----|------|------|\n");
for (a = false; a <= true; a++)
for (b = false; b <= true; b++)
printf ("| %d %d | %d | %d |\n",a, b, (a && b), (a || b));
return 0;
}
Ergebnis:
| a b | a&&b | a||b |
|-----|------|------|
| 0 0 | 0 | 0 |
| 0 1 | 0 | 1 |
| 1 0 | 0 | 1 |
| 1 1 | 1 | 1 |
Bitmanipulationen
C stellt auch Operatoren für Bitmanipulationen zur Verfügung.
Die Verknüpfung der beiden Operanden erfolgt bitweise.
Sie können nicht auf Variablen oder Konstanten vom
Typ float oder double angewendet werden. Die Operatoren
sind:
~ | Komplement |
<< | Linksshift |
>> | Rechtsshift |
& | bitweises UND |
^ | bitweises EXKLUSIVES ODER |
| | bitweises ODER |
Beispiele:
int i=7;
int j=9;
int k;
k = i & j; /* k=1 */
k = i | j; /* k=15 */
k = i ^ j; /* k=14 */
k = ~0 /* k=max(unsigned int) */
k = ~i; /* k=max(unsigned int) -7 */
k = i << 3; /* k=56 */
k = i >> 3; /* k=0 */
k = i & 0x03; /* k=3; alle Bits bis auf die beiden */
/* unteren ausmaskiert */
Beispiel: Zählen der Anzahl der 1-Bits in n
bitcount(unsigned int n)
{
int b;
for (b=0; n!=0; n >>= 1)
if (n & 01)
b++;
return (b);
}
Zweite, schnellere Version:
bitcount(unsigned int n)
{
int b;
b=0;
while (n != 0)
{
b++;
n = n & (n-1);
}
return (b);
}
Das folgende Beispiel ermittelt die Länge eines Maschinenwortes
durch Zählen der Bits.
#include <stdio.h>
int wordlen()
{
int i;
unsigned wort;
i = wort = 0;
wort = ~wort; /* alle Bits auf 1 setzen */
while (wort != 0)
{
wort = wort >> 1; /* rechtsschieben */
i++;
}
return(i);
}
main()
{
printf("Anzahl der Bits: %d\n",wordlen());
}
Wichtig:
- es werden teilweise die gleichen Operatorzeichen für verschiedene
Operatoren verwendet
Operator- zeichen | 1. Bedeutung | 2. Bedeutung |
() | Klammerung | typecast |
* | Pointerdeklaration | Multiplikation |
- | Vorzeichen | Subtraktion |
& | Adresse von | bitweises UND |
- Inkrement- und Dekrementoperatoren haben einen sehr hohen Vorrang
- die Arithmetikoperatoren haben einen Vorrang wie erwartet und gewohnt
- Shifts haben einen höheren Vorrang als Vergleiche, im Gegensatz
zu den anderen Bitmanipulationen, die nach den Vergleichen stehen.
- bitweise logische Operationen stehen vor den logischen Operationen,
die sich auf ganze Zahlen beziehen.
- die bedingte Bewertung hat einen sehr niedrigen Vorrang, trotzdem
sollte man sich bei ihrer Anwendung eine Klammerung angewöhnen,
damit die Anweisung leichter lesbar ist.
- außer durch den Vorrang ist die Reihenfolge der Bewertung
undefiniert: z = (a*2) + ++a kann als (a*2)+ ++a
aber auch als ++a + (a*2) bewertet werden. Seiteneffekt!
- ebenso ist die Reihenfolge der Bewertung von Funktionsparametern
nicht gewährleistet:
i=1;
printf("%d %d",++i,i*3) /* kann 2,6 oder 4,3 ausgeben */
- ebenfalls nicht eindeutig definiert ist folgende Konstruktion:
a[i]=i++;
- Dagegen bedeutet x---y: x-- - y und nicht x - --y.
Der Compiler führt seine lexikalische Analyse immer von links nach rechts aus
und nimmt dabei soviele Zeichen, wie er nur kann, um ein Token zu bilden.
|