Was ist der Unterschied zwischen if / else if und 2x if?

4 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Bei "else if (...)" wird die zweite Bedingung nur dann geprüft, wenn die erste Bedingung nicht erfüllt war.

if (a) { it_was_a(); } else if (b) { it_was_b_but_not_a(); }

... ist somit semantisch IN ETWA (nicht ganz, aber fast) vergleichbar mit ...

if (a) { it_was_a(); }
if ((!a) && (b)) { it_was_b_but_not_a(); }

... heißt: Wenn Du das zweite "if" in den "else"-Zweig des ersten packst (was Du mit einem "else if" faktisch tust), dann wird die zweite Bedingung überhaupt nur dann geprüft, wenn die erste NICHT zutraf, beziehungsweise bei längeren Ketten aus "if (...) { ... } else if (...) { ... } else if (...) { ... }" wenn KEINE der vorangegangenen Bedingungen zutraf.

Also ein ODER-Gied?

Oder ein " If-OR".......gg................

1
@Lichtkurier

Es ist definitiv kein logisches (boolsches) Oder (or). Ganz plumpes Beispiel, wo es einen Unterschied gibt.

bool a = true;
bool b = true;

if (a) { do_a(); }
if (b) { do_b(); }

/* Sowohl do_a() als auch do_b() werden aufgerufen! */

Hingegen ...

bool a = true;
bool b = true;

if (a) { do_a(); }
else if (b) { do_b(); }

/* Nur do_a() wird aufgerufen, da die zweite
Bedingung sich im "else-Zweig" der ersten
befindet und daher nur geprüft wird, falls
die erste Bedingung NICHT zutraf! */
3
@Lichtkurier

Ein "else if" macht quasi zur Voraussetzung, dass die zweite Bedingung überhaupt geprüft wird, dass bei der vorhergehenden Bedingung der bedingte Code nicht durchlaufen wurde.

Es ist letztlich eine weitere Bedingung ("if") im "else"-Zweig der vorangegangenen.

if (a)
{
   do_a();
}
else if (b)
{
    do_b();
}

... ist letzten Endes nur eine "schönere Schreibweise" für ...

if (a)
{
    do_a();
}
else
{
   if (b)
   {
      do_b();
   }
}

Letztlich "sieht" der Compiler genau das selbe. Die zweite "if-Anweisung" befindet sich im "else-Zweig" der ersten "if-Anweisung". Wenn nur eine einzelne Anweisung folgt (in diesem Fall eben eine "if-Anweisung"), sind die geschweiften Klammern ja optional.

Ich könnte also auch schreiben ...

if (a)
   do_a();
else if (b)
   do_b();

... und das ist ja äquivalent (nur anderer Whitespace und Whitespace trägt ja in C keine Bedeutung) zu folgendem Code ...

if (a)
   do_a();
else
   if (b)
      do_b();

Dann verstehst Du vielleicht, was passiert. ;-)

Nur falls "a" nicht zutrifft, prüfe "b" ...

... und falls das zutrifft, führe "do_b()" aus.

2

Du willst - bzw Dein Programm soll Tomaten kaufen. Aber mindestens fünf, damit jeder eine kriegt. Wenn bei Kauf von mindestens 25 Stück Tomaten im Sonderangebot sind, gibt es Tomatensuppe am Wochenende .. dafür müssen es aber mindestens 25 Tomaten sein (dann mußt Du natürlich die 5 einzelnen nicht mehr kaufen):

wenn ( ware=tomate ) - { tomatenzähler + 1 } wenn ( tomatenzähler >=25 Stück und tomatenpreis=sonderpreis ) - { 25 Stück kaufen } sonst, nur wenn außerdem auch ( tomatenzähler>=5 ) - { 5 Stück kaufen }

machst Du das unverschachtelt mit     if . . . if . . .     hast Du nachher 30 Tomaten. Das geht zwar zu verhindern mit Zusatzbedingung für die 5 Einzelnen (wenn nicht schon gekauft .. oder wenn nicht Sonderpreis zB). Ist aber überflüssig. Mit Verschachtelung wird die Bedingung gar nicht erst mehr geprüft .. der Programmfluß kann sie zeitsparend übergehen.

Beim zweiten Fall wird das zweite if nur überprüft, wenn das erste falsch ergeben hat.

Wenn du zum beispiel ein Objekt mit einer Reihe andere Objekte vergleichen willst, aber nur eins passt, ist das sinnvoll.

Wobei man dann eher switch-case nimmt.

Gerade "switch-case" funktioniert in vielen Sprachen nur mit einfachen Datentypen (z. B. int), nicht mit Objekten (z. B. String), da es in Maschinensprache in eine Jump-Table übersetzt wird, also eine Tabelle mit Werten und Sprungzielen (Adressen, auf die ein "branch"-Statement zeigt). Der Vergleich von Objekten läuft aber häufig (sofern man nicht lediglich die Referenzen/Pointer vergleicht) so, dass das Objekt eine "compare"-Methode aufruft. Das muss dann in Maschinensprache zu einem Unterprogrammaufruf ("call"-Statement) übersetzt werden. Damit fällt die Jump-Table flach. Daher funktionieren in vielen Sprachen "switch-case"-Statements nur mit primitiven Datentypen bzw. häufig auch nur mit numerischen Datentypen.

0
@NoHumanBeing

Ich denke, es wäre bescheuert, wenn es nicht auch mit Objektreferenzen geht.

Siehe enums oder Exemplarobjekte.

1