6.2. Äquivalenz- und Vergleichsoperatoren

Die Bedingung einer if-Anweisung besteht meist aus einem Ausdruck, der einen Vergleich zwischen Variablen, Konstanten und (oder) arithmetischen Ausdrücken darstellt. Um die Gleichheit oder Ungleichheit von Operanden eines Ausdrucks bestimmen zu können, verfügt C über Äquivalenz- und Vergleichsoperatoren. Alle diese Operatoren sind binär, d.h., sie erfordern zwei Operanden.

Das Ergebnis einer Vergleichsoperation hat immer den Wert 0 oder 1, dabei steht 0 für "falsch", 1 für "wahr". Dieses Ergebnis kann bei Bedarf in arithmetischen Ausdrücken verwendet oder einer Funktion als Argument übergeben werden. Auf diese Weise läßt sich der Wahrheitswert eines Vergleichs mit printf() darstellen:


.
.
printf("Wert für wahr: %d\tWert für falsch: %d\n",
		2 < 3,
	 	7 != 7);
.
.

Äquivalenzoperatoren:

Operator Bedeutung
== gleich
!= ungleich

Vergleichsoperatoren:

Operator Bedeutung
<= kleiner oder gleich
< kleiner
> größer
>= größer oder gleich

Die Vergleichs- und Äquivalenzoperatoren haben, wie auch die arithmetischen Operatoren, eine Priorität und Assoziativität. Alle vier Vergleichsoperatoren genießen den gleichen Vorrang — der aber ist geringer als jener von arithmetischen Operatoren — und sind von links nach rechts assoziativ. Die beiden Äquivalenzoperatoren haben geringere Priorität als die Vergleichsoperatoren und sind ebenfalls von links nach rechts assoziativ.

Die Assoziativität der Vergleichs- und Äquivalenzoperatoren ist nur von geringem praktischen Nutzen: Die Auswertung eines Teilausdrucks ergibt immer 1 oder 0, je nachdem, ob er wahr oder falsch ist. Dieses Ergebnis wird dann mit dem nächsten Operanden verglichen. Ein Ausdruck, der mehrere Vergleichs- oder Äquivalenzoperatoren enthält, führt zu unerwarteten Ergebnissen, sofern man die in der Mathematik übliche Bewertung voraussetzt.


.
.
int iCount = 5, iBegin = 0;
unsigned short usEnd = 10;

if( iBegin < iCount < usEnd )
	 printf("%d",iCount);
.
.

Wer erwartet, daß die Anweisung printf("%d",iCount) ausgeführt wird, weil die Bedingung der if-Anweisung richtig ist, hat recht - wenn auch möglicherweise mit der falschen Begründung.

Der Ausdruck iBegin < iCount < usEnd ist nicht deswegen wahr, weil iCount größer als iBegin und kleiner als iEnd ist, sondern weil der dritte Operand größer als das Ergebnis des ersten Teilausdrucks ist:

Aufgrund der Links-nach-rechts-Assoziativität des Vergleichsoperators ’<’ wird zuerst iBegin < iCount ausgewertet. Das Ergebnis ist 1 (steht für "wahr"), da iBegin kleiner als iCount ist. Der nächste Vergleich lautet dann 1 < usEnd, was ebenfalls zutrifft. Damit ist der ganze Ausdruck wahr. In der Praxis ist mit derartigen Ausdrücken jedoch nichts anzufangen. Um das Anliegen, das dieser Konstruktion zugrunde liegt, formulieren zu können — nämlich festzustellen, ob iCount größer als iBegin und kleiner als iEnd ist — bedürfen wir zusätzlich logischer Operatoren (siehe dazu Kapitel 6.4.).

Das Beispielprogramm, mit dem wir unter Verwendung von getch() den Scancode von Funktionstasten abgefragt haben, läßt sich mit Hilfe einer if-Anweisung so gestalten, daß wir unterscheiden können, ob eine Sondertaste oder eine gewöhnliche Taste gedrückt wurde. Nur unter der Bedingung, daß cChar 0 ist, d.h. eine Sondertaste vorliegt, muß getch() ein zweites Mal aufgerufen werden.


/******************************************** ******
 *                  extended.c                    *
 * erweiterten Scancode von Sondertasten abfragen *
 ********************************************* *****/

#include <stdio.h> /* wg. printf() */
#include <conio.h> /* wg. getch() */

int main(void){

int iExtended;
char cChar;

	 printf("Bitte eine Taste drücken...\n");
	 cChar = getch();

	/* Wert für Funktionstaste nur ermitteln,
	 * wenn cChar den Wert 0 hat
	 */
	if( cChar == 0 )
		{
		iExtended = getch();
		printf("Sondertaste mit Scancode %d wurde"

			"betätigt\n", iExtended);
		}
	else
		 printf("%c-Taste wurde betätigt", cChar );

return 0;
}

Es ist zu beachten, daß weder die if- noch die else-Anweisung mit einem Semikolon abgeschlossen wird; ein Semikolon nach if oder else hieße für den Compiler, daß der jeweilige Zweig damit beendet ist. Enthielte unser Beispielprogramm ein Semikolon nach else, dann würde der folgende printf()-Aufruf immer ausgeführt, weil er außerhalb des else-Zweiges stünde; ein Semikolon nach dem if führt allerdings zu einer Fehlermeldung, da das else nicht mehr dem if zugeordnet werden könnte. Ebensowenig kann nach der if-Anweisung auf die geschweiften Klammern verzichtet werden, da ansonsten nur die erste Anweisung nach if von der Bedingung cChar == 0 abhinge. Alle folgenden Anweisungen würden dann immer ausgeführt; zudem könnte das else dem if nicht mehr zugeordnet werden, weil dieses nicht direkt auf den if-Block folgte. Dies zöge ebenfalls eine Fehlermeldung des Compilers nach sich.