6.4. Logische Operatoren
Zur Formulierung komplexer Ausdrücke in Vergleichen bietet C logische Operatoren an. Diese sind:
Operator | Bedeutung |
---|---|
&& | und |
|| | oder |
! | Negation |
Bei && und || handelt ist sich um binäre Operatoren, der Negationsoperator hingegen verlangt nur einen Operanden. Die logischen Operatoren behandeln ihre Operanden als logische Werte, d.h., diese gelten als falsch, wenn sie gleich 0 sind, ansonsten als wahr. Anhand eines weiter oben verwendeten Beispiels läßt sich nun unter Verwendung von logischen Operatoren die gleichzeitige Bewertung mehrerer Vergleiche demonstrieren:
.
.
int iCount = 5, iBegin = 0, usEnd = 10;
/* && hat höhere Priorität als <
* Klammern wären nicht notwendig,
* erhöhen aber die Lesbarkeit
*/
if( (iBegin < iCount) && (iCount < usEnd) )
printf("%d",iCount);
.
.
In diesem Fall wird printf() ausgeführt, weil iCount größer als iBegin und kleiner als iEnd ist. Die Auswertung der Bedingung geschieht folgendermaßen:
- (iBegin < iCount) ist wahr und resultiert im logischen Wert 1
- (iCount < iEnd) ist wahr und hat ebenfalls 1 zum Ergebnis
- Die logische Bewertung 1 && 1 ist wahr, das bedeutet, der ganze Ausdruck ist wahr.
Folgende Wahrheitstabelle zeigt alle möglichen Kombinationen aus Wahrheitswerten mit den logischen Operatoren && sowie || und listet deren Ergebnisse auf:
p | q | p && q | p || q |
---|---|---|---|
wahr | wahr | wahr | wahr |
wahr | falsch | falsch | wahr |
falsch | wahr | falsch | wahr |
falsch | falsch | falsch | falsch |
Ziemlich einfach stellt sich die Wirkung des Negationsoperators dar: Ist ein Wert wahr, d.h., ist er ungleich 0, dann setzt ihn die Negation auf 0, also auf falsch. Umgekehrt setzt die Negation eines falschen Wertes diesen auf wahr.
Es ist zu beachten, daß nicht alle drei logischen Operatoren den gleichen Vorrang besitzen. Der unäre Negationsoperator ! hat die höchste Priorität; der Operator && genießt die zweithöchste Priorität vor dem schwächsten Operator ||.
Angenommen, in einem Programm werden die Variablen
int iCount = 0, iAge = 33, iStep = 3;
char cInit = 'A';
definiert. Dann haben folgende logische Verknüpfungen die angeführten Ergebnisse:
Verknüpfung | Ergebnis |
---|---|
!iStep | Alle Werte != 0 stehen für "wahr", die Negation davon ist "falsch", also Ergebnis 0. |
iCount && iAge || iStep | 0 && 33 ergibt 0, 0 || 3 ist "wahr". |
!(cInit && iCount) | 'A' && 0 ergibt "falsch", die Negation davon ist "wahr". |
!iCount && iStep | !iCount wird vor && ausgewertet und ergibt 1, 1 && 3 ist "wahr". |
(iStep <= iAge) || !Count | 3 ist tatsächlich <= 33 und ergibt daher 1; 1 || !iCount ist "wahr". |
(iAge — 30) != iStep | "Falsch", da 33 — 3 nicht ungleich 3 ist. |
Um die Verwendung von logischen Operatoren innerhalb einer else-if-Konstruktion zu demonstrieren, wollen wir ein letztes Mal unser Beispiel zur Abfrage von Sondertasten strapazieren. Wir können nun durch das Abfragen zusätzlicher Bedingungen feststellen, ob eine Funktionstaste zusammen mit den Tasten (Alt) , (Shift) oder (Strg) gedrückt wurde.
/**************************************************
* extended.c *
* Scancode von Funktionstasten in Kombination *
* mit ALT, STRG und SHIFT abfragen *
**************************************************/
#include <stdio.h> /* wg. printf() */
#include <conio.h> /* wg. getch() */
int main(void){
int iExtended=0;
unsigned char ucChar;
printf("Bitte eine Taste drücken...\n");
ucChar = getch();
/* Sondertaste liegt nur vor, wenn ucChar
* den Wert 0 hat
*/
if( ucChar == 0 ){
iExtended = getch();
if( iExtended >= 59 && iExtended <= 69 )
printf("Funktionstaste F%d wurde betätigt\n",
iExtended - 58);
else if( iExtended >= 84 && iExtended <= 93 )
printf("Shift + Taste F%d wurde betätigt\n",
iExtended —
83);
else if( iExtended >= 94 && iExtended <= 103 )
printf("Strg + Taste F%d wurde betätigt\n",
iExtended - 93);
else if( iExtended >= 104 && iExtended <= 113 )
printf("Alt + Taste F%d wurde betätigt\n",
iExtended —
103);
else
printf("Taste mit Scancode %d betätigt!",
iExtended);
}
else
printf("Taste \'%c\' wurde betätigt", ucChar );
return 0;
}
Die else-if-Konstruktion erweitert die bisherige Version von extended.c um Bedingungen, die es zulassen, den Scancode der gedrückten Tasten genauer aufzuschlüsseln. Bei der Formulierung der einzelnen Bedingungen können mit Hilfe des logischen Operators && die Wertebereiche abgesteckt werden, innerhalb der die jeweiligen Tastenkombinationen definiert sind.
Gelegentlich finden sich in C-Programmen Ausdrücke wie
if(!iCount)
printf("Das Ergebnis ist %d", ulSum);
Die Bedingung des if-Ausdrucks reduziert sich auf eine Variable, deren Wahrheitswert negiert wird. Scheinbar findet hier kein Vergleich statt. Tatsächlich handelt es sich bei dieser Bedingung aber um einen impliziten Vergleich, der jederzeit explizit gemacht werden kann. Was will ein C-Programmierer mit einer derart formulierten Bedingung ausdrücken? Ohne Verwendung des Negationsoperators wäre die Bedingung richtig, wenn die Variable iCount einen Wert ungleich 0 besitzt. Der Negationsoperator verkehrt den logischen Wert eines Ausdrucks, d.h., die Bedingung if( !iCount ) ist dann richtig, wenn iCount den Wert 0 annimmt. Es fällt auf, daß die Bedeutung eines solchen Ausdrucks relativ schwer zu erschließen ist. Der ersparten Tipparbeit und der Freude über besonders "schlauen" Code steht also der Nachteil einer schlecht lesbaren Formulierung gegenüber. Besser läßt sich dieses Fragment also unter Verwendung eines expliziten Vergleichs schreiben:
if( iCount == 0 )
printf("Das Ergebnis ist %d", ulSum);