Gleichheitsprüfungen in C
Der Operator »==«
vereinfachte Syntax
Ausdruck
.----------. .--. .----------.
--->| Ausdruck |--->( == )-->| Ausdruck |--->
'----------' '--' '----------'
Man beachte die Unterscheidung zwischen dem Zuweisungsoperator »=« und dem Gleichheitsoperator »==«. Beide sind jeweils eine lexikalische Einheit, die erste schreibt sich jedoch mit einem Gleichzeichen »=«, die zweite mit zwei Gleichzeichen »==«.
Selbst, wenn man dies weiß, ist es ein häufiger Flüchtigkeitsfehler, versehentlich statt »==« den Operator »=« zu verwenden.
Wenn keine Verwechslungen mit einer Zuweisung zu befürchten sind, kann man diesen Operator als „gleich“ aussprechen. Sind Verwechslungen zu befürchten, so muß er genauer als „Gleichheitsprüfung“ oder ähnlich bezeichnet werden.
Die mathematische Schreibweise dieses Operators ist ‹=› (ein einfaches Gleich-Zeichen). (Für die C -Zuweisung »=« gibt es in der Mathematik keine genaue Entsprechung.)
Priorität
Die folgende Tabelle gibt die Assoziativität und Priorität der bisher behandelten Operatoren wieder.
- Priorität und Assoziativität der bisher behandelten Operatoren
() Eingeklammerter Ausdruck
() Aufrufoperator
+ - ! Unaere vorangestellte Operatoren
L * / Multiplikation, Division
L + - Addition, Subtraktion
L == Gleichheitspruefung
L && Und
L || Oder
R = Zuweisung
Typanforderungen (vereinfacht)
Prüfungen der Gleichheit von Zeichenfolgen werden erst später behandelt werden. Der hier vorgestellte Operator sollte dafür bis auf weiteres nicht herangezogen werden, da die genauen Regeln dafür erst später erklärt werden werden.
Prüfungen der Gleichheit von Gleitkommawerten sind normalerweise nicht nützlich, weil die genaue Gleichheit auch Gleichheit in den hinteren Stellen mit einschließt, aber die hinteren Stellen kaum eine Bedeutung haben oder durch kleine Fehler bei der Darstellung einer Zahl verfälscht worden sein könnten.
Obwohl die Gleichheitsprüfung grundsätzlich mit allen bisher vorgestellten Datentypen verwendet werden kann, ist sie daher in der Regel nur zum Vergleich zweiter ganzzahliger Werte sinnvoll.
Typangleichung
Der Wert von »7« und der Wert von »7.« sind unterschiedlich, da diese Ausdrücke zwei verschiedene Datentypen haben. Bei der Prüfung »7==7.« wird der Wert »7« aber zunächst nach double gewandelt. Es wird dann praktisch »7.==7.« ausgewertet. Daher ergibt »7==7.« true, obwohl die Werte eigentlich unterschiedlich sind, da sie sich in den Datentypen unterscheiden. Dies führt aber in der Praxis nicht zu Problemen, sondern ist meist eher nützlich. Falls einem dies mißfällt, kann man ja darauf verzichten Ausdrücke unterschiedlicher Typen auf Gleichheit zu prüfen oder sich eine eigene Funktion für Vergleiche definieren.
Typ des Ausdrucks
Der Typ eines mit diesem Operator gebildeten Ausdrucks zur Gleichheitsprüfung ist immer »int«.
Semantik
Haben beide Ausdrücke (nach einer Typangleichung) denselben Wert, so ist der Wert der Gleichheitsprüfung »1«, sonst »0«. (Dies ist anders als bei gewissen Prädikaten, die für Wahrheit irgendeinen anderen Wert als 0 ergeben.)
Die Werte der letzten drei Gleichheitsprüfungen in dem folgenden Beispiel sind implementationsspezifisch, was wieder zeigt, daß Vergleiche von Gleitkommawerten in der Regel nicht sinnvoll sind.
main.c
#include <stdio.h> int main( void )
{ printf( "%d\n", 1 == 2 );
printf( "%d\n", 0.0 == 0.00 );
printf( "%d\n", 2.0 == 1.9999999999999999 );
printf( "%d\n", 2.0 == 1.9999999999999999999 );
printf( "%d\n", 2.0 == 1.99999999999999999999 ); }- stdout (Implementation A)
0
1
1
1
1- stdout (Implementation B)
0
1
0
0
1
Der Ausdruck »!(A )« hat für einen Ausdruck A denselben Wert wie »(0==(A ))«.
Bei double /double -Vergleichen kann das Ergebnis des Vergleichs anders sein als man es erwartet, wenn man die Rechnungen im Kopf durchführt.
main.c
#include <stdio.h> int main( void )
{ printf( "%d\n", 0.1 + 0.2 == 0.3 );
printf( "%d\n", 1.1 * 1.1 == 1.21 ); }- stdout (Implementation A)
0
0- stdout (Implementation B)
1
1main.c
#include <stdio.h> int main( void )
{ printf( "%d\n", "a" == "a" );
printf( "%d\n", "a" == "b" ); }- stdout (Implementationsspezifisch!)
1
0
Obwohl der Vergleich der Zeichenfolgen hier vielleicht das vom Leser erwartete Ergebnis hat, ist es doch im allgemeinen nicht sinnvoll, Zeichenfolgen mit »==« zu vergleichen. Das Verhalten ist in der Regel implementationsspezifisch! Um Zeichenfolgen zu vergleichen, muß eine Funktion wie »strcmp« verwendet werden.
Gleichheitsprüfung und Datentypen
Zeichenfolgen sollten im allgemeinen nicht mit »==« verglichen werden.
Auch bei Gleitkommazahlen ist der Vergleich mit »==« im allgemeinen nicht sinnvoll. (Ausnahmen sind einige Situationen, bei denen die beschränkte Genauigkeit keine Rolle spielt.)
Daher bleibt nur der Datentyp »int« übrig:
Vorerst kann man »==« als Operator zum Vergleich ganzzahliger Werte ansehen.
Der Operator »!=«
Dieser Operator wird „ungleich“ oder „ist nicht gleich“ gesprochen und steht für die Verneinung der Gleichheit. Für zwei Variablen »x« und »y«, ist »x==y« also beispielsweise wahr genau dann, wenn »x!=y« falsch ist.
»x!=y« kann man auch schreiben als »!(x==y)«.
Übungsfrage
Was gibt das folgende Programm aus?
main.c
#include <stdio.h> void d( int const n )
{ int result;
if( n == 0 )result = 0;
if( n == 1 )result = 2;
if( n == 2 )result = 4;
if( n == 3 )result = 6;
else result = 8;
printf( "%d\n", result ); } int main( void )
{ d( 0 );
d( 1 );
d( 2 );
d( 3 );
d( 4 );}
Übungsfragen
- Wie kann die Anzahl der Operatoren in der folgenden Anweisung vermindert werden (»zahl« habe den Datentyp »int«)?
- Anweisung
if( zahl != 0 )printf( "nicht Null\n" );
Übungsfrage
Wie kann man die folgende Funktionsdefinition vereinfachen (im dem Sinne, daß ihr Quelltext möglichst kurz wird)?
- Funktionsdefinition
int n( int const w )
{ int result;
if( w != 0 )result = 1;
else result = 0;
return result; }