Folgend eine Auflistung aller in C vorhandenen Sprachelemente, die zusammen die Syntax bilden. Die Art und Weise, wie diese Elemente zusammengesetzt werden dürfen, wird bei jedem Teil einzeln beschrieben.
4.1. Zuweisungen
Eine Sprache lebt von ihren Variablen, und diese können in C verschiedenartigst verknüpft werden. Grundsätzlich wird, wie bereits erwähnt, von rechts nach links vorgegangen. Das heißt, dass zuerst das Ergebnis der rechts neben der Zuweisung stehenden Sequenz berechnet wird und dann dem \"Empfänger\" auf der linken Seite zugewiesen wird. Eine sehr einfache Sequenz sieht wie folgt aus:
x = a;
Bei obiger Anweisung wird der Inhalt der Variable a in die Variable x geschrieben. Wichtig ist hierbei, dass beide Variablen vom selben Typ sind. Eine Umformung in einen anderen Typ wird später genau erklärt. Steht rechts neben dem = eine Sequenz, dann könnte die vorige Anweisung folgend aussehen:
x = a*2;
Hierbei wird zuerst das Ergebnis der Berechnung a*2 ermittelt und anschließend in die Variable x geschrieben. Dies ist ohne das Setzen von Klammern möglich, da der Operator \'*\' eine höhere Priorität besitzt, als das \'=\'. Folgend mögliche Vereinfachungen von Zuweisungen:
x = x*2; entspricht: x *= 2;
x = x+10; entspricht: x += 10;
x = x+1; entspricht: x += 1; oder: x++;
Die gleichen Vereinfachungen können auch mit den Operatoren für die Subtraktion und Division durchgeführt werden.
Des weiteren können auf der rechten Seite auch Funktionen aufgerufen werden (sofern diese einen Wert zurückliefern). Möchte man mit dem Ergebnis einer Funktion arbeiten, so ist dies auch möglich:
x = sin(y) * 2;
Die Funktion sin(y) liefert einen Wert zurück, der mit 2 multipliziert und erst anschließend x zugewiesen wird. Dies funktioniert deshalb, weil der Aufruf einer Funktion die höchste Priorität besitzt. Hat der Compiler den Aufruf abgearbeitet, ersetzt er ihn durch den zurückgelieferten Wert. Dieser wird dann für die weitere Berechnung hergenommen. Ein Beispiel für die mögliche Verschachtelung in C:
x = sin(abs(y[i]) * 2) - t/2;
Wie bereits erwähnt, geht der Compiler hier von innen nach außen vor. Das bedeutet, dass er sich zuerst die innerste Anweisung sucht. Diese ist in obigem Fall die Ermittlung des Feldwertes y[i]. Danach berechnet er den Absolutwert des Ergebnisses abs(y[i]).Hat der Compiler diese Anweisung abgearbeitet, multipliziert er den ermittelten Wert mit zwei und übergibt das Ergebnis an die Funktion sin. Als Abschluss wird dem Ergebnis von sin noch ein Quotient abgezogen.
4.2. Selektion, Abfrage
In C gibt es drei verschiedene Möglichkeiten, eine Abfrage zu realisieren. Sie unterscheiden sich in einigen wichtigen Punkten von einander, können jedoch trotzdem durch die Standardabfrage ersetzt werden.
4.2.1. if - else
Die Standardabfrage in C ist die if - else Abfrage. Sie besteht aus zwei Teilen, der Erfüllung einer Anweisung, bzw. ihrer Nicht-Erfüllung.
if({Anweisung}){
...
}else{
...
}
Auf eine if-Abfrage folgt kein Strichpunkt! Ein sehr häufig auftretender Fehler, vor allem bei Anfängern. Zwischen den geschwungenen Klammern können beliebig viele Anweisungen stehen, welche durch einen Strichpunkt zu terminieren sind. Gleiches gilt für den else Teil. Bsp.:
if(x == 10){ //Ist der Wert 10?
a = 5; //wenn ja, dann werden diese Anweisungen ausgeführt
x++;
}else{
a=0; //wenn nein, werden diese Anweisungen ausgeführt
}
Folgt auf einer Abfrage nur eine Sequenz, so können die geschwungenen Klammern entfallen. Bsp.:
if(x == 10)
a = 0;
else
a = 5;
Eine if - Anweisung gilt als wahr, wenn die Abfrage einen Wert ungleich Null zurückliefert. Im obigen Beispiel liefert der Operator == einen Wert gleich Null zurück, wenn x nicht 10 ist und einen Wert ungleich 0, wenn x 10 ist. Eine Abfrage, ob eine Variable ungleich 0 ist kann daher auf folgendes reduziert werden:
x=10;
if(x) //Die Anweisung in den beiden runden Klammern entscheidet darüber, ob der Wahr - //Teil, oder der Falsch - Teil einer if Anweisung ausgeführt werden soll. In diesem //Fall wird der Wahr - Teil ausgeführt, da x ungleich 0 ist. Währe x 0, dann würde der //Falsch - Teil ausgeführt werden.
Wie alles in C, können auch if Abfragen verschachtelt werden, das heißt, dass in einem else - Teil z.B. eine weitere Abfrage stecken kann. Wie tief verschachtelt werden darf hängt wieder vom Compiler ab.
4.2.2. switch - case
Diese Abfrage wird verwendet, wenn eine Variable nicht nur auf zwei gegensätzliche Merkmale hin überprüft werden soll, sondern eine große Anzahl an möglichen Zuständen existiert. Grundlegendes Aussehen:
switch({Variable}){
case {Abfrage}:...
case {Abfrage}:...
...
default: ...
}
Die Variable kann eine nummerisch oder auch durch mit enum ersetzte Konstanten enthalten. Diese werden in den case Abschnitten auf gewisse Merkmale hin überprüft. So kann eine normale switch - case Anweisung folgend aussehen:
switch(x){
case 0: a = 5; ... break;
case 4: a = 10; ... break;
case 7: a = 0; ... break;
default: a = -a; break;
}
Die Variable x wird hier auf drei verschiedene Werte hin überprüft. Je nachdem, welchen Wert sie enthält, werden unterschiedliche Anweisungen ausgeführt, die selbstverständlich ihrerseits auch wieder Abfragen enthalten können. Das Schlüsselwort break wird hier verwendet, um die Ausführung zu beschleunigen, da es zur Übergeordneten Anweisung schaltet. Das bedeutet, dass nach Aufruf von break der case Teil verlassen und in den switch Teil, der in diesem Fall den übergeordneten darstellt, gewechselt wird. Daraus ist ersichtlich, dass alle anderen case Abfragen keine Bedeutung mehr haben, da der switch Teil beendet ist. Das Schlüsselwort default bezeichnet eine Reihe von Anweisungen, die ausgeführt werden, wenn keiner der case Zweige zutrifft. Eine case Abfrage kann auch mehrere, durch einen Beichstrich getrennte Parameter erhalten:
case 0, 5, 7: ...
Die obige Abfrage ist also wahr, wenn einer der drei Parameter als wahr gilt.
4.2.3. Ternärer Operator
An sich nur eine Vereinfachung des zweiwertigen if Operators, dient der ternäre vor allem zur Verkürzung von Ausdrücken. Aussehen:
{Anweisung 1} ? {Anweisung 2} : {Anweisung 3};
Gilt Anweisung 1 als wahr, wird Anweisung 2 ausgeführt, ansonsten Anweisung 3. Wie ersichtlich ist, ist der ternäre Operator lediglich eine if - else Bedingung.
Bsp.:
(x>10) ? a = 5 : a = 0;
Ist der Wert von x größer als 10, wird die Anweisung a = 5 ausgeführt. Andernfalls wird a auf 0 gesetzt.
4.3. Iterationen, Schleifenbildung
Um die drei Grundelemente abzuschließen, sollen jetzt noch die Schleifen behandelt werden. In C gibt es hierzu drei verschiedene Möglichkeiten, die sich durch die Positionierung der Abfrage unterscheiden. Grundlegend ist zu sagen dass man bei Iteration zwischen zwei verschiedenen Arten unterscheidet: definite und indefinite.
Bei definiten Iterationen ist die Anzahl der Durchläufe bekannt und man kann daher voraussagen, wie lange sie dauern wird. Indefinite Schleifen hingegen, besitzen keine eigentliche Abbruchbedingung, und laufen unbestimmt lange. Bei jedem der folgenden Schleifentypen kann eine Definition indefinit oder definit sein.
Bei der Positionierung der Abbruchbedingung unterscheidet man zwischen pretested und posttested, was bedeutet, dass die Abbruchbedingung im Kopf (pre) oder im Fuß (post) der Schleife liegt. Schleifen, die im Fuss kontrolliert werden, laufen zumindest einmal durch. In C wird die Abfrage zur Abbruchbedingung bei jedem Schleifendurchlauf erneut ausgeführt, was zu Geschwindigkeitsverlusten führen kann, wenn die Abbruchbedingung eine komplexere Anweisung ist.
4.3.1. while
Die klassische Schleife in C. Sie wird im Kopf getestet. Folgendes Aussehen:
while({Bedingung}){
{Anweisung}
{Anweisung}
...
}
Die Schleife durchläuft alle Anweisungen, solange die Bedingung wahr ist. Trifft die Bedingung nicht mehr zu, das heißt sie ist falsch, wird die Schleife abgebrochen. Dadurch, dass sie im Kopf getestet wird, ist die minimale Anzahl an Durchläufen Null. Wie auch bei den Abfragen gilt hier die Regelung, dass die geschwungenen Klammern weggelassen werden können, wenn nur eine Anweisung folgt. Dies gilt im übrigen bei allen drei Schleifen.
Bsp.:
while(x |