IF-ELSE ohne Anweisung im else-Zweig

Gast #1495789
Lesenswert?
• ▲
▼
Ich habe in einem fremden Code einen komischen IF-ELSE-Konstrukt 
gefunden:

In einer Funktion steht folgendes:

if( count = 100 )
{
   // mache etwas
}
else

switch(time)
{
   case:    //usw.
   default: //usw.
}


Gehört die switch-ANweisung noch zum ELSE-Zweig? Nein oder, weil dort 
meiner Meinung nach doch die {}-Umklammerung fehlt.

Also dachte ich eher, dass ganze wäre mit folgendem äquivalent:

if( count = 100 )
{
   // mache etwas
}
else
{
}

switch(time)
{
   case:    //usw.
   default: //usw.
}

Doch leider ist die Funktionalität dadurch eine andere. Kann mir das 
bitte jemand erklären? Das gehört doch auf keinen Fall dem 
ANSI-C-Standard an?

VIELEN DANK.
#1495795
Lesenswert?
• ▲
▼
Sven Schol schrieb:

> Gehört die switch-ANweisung noch zum ELSE-Zweig?

Ja.

> Nein oder, weil dort
> meiner Meinung nach doch die {}-Umklammerung fehlt.

Bei nur einer Anweisung braucht man keine Klammern.

> Das gehört doch auf keinen Fall dem
> ANSI-C-Standard an?

Doch, und genauso jedem anderen C-Standard.
Gast #1495796
Lesenswert?
• ▲
▼
Jedes C-Buch gibt darueber Auskunft. Und auch, warum es eine dumme Idee 
ist, die Klammern wegzusparen (dangling else problem), obwohl es erlaubt 
ist. Kurz gefasst: Nach dem else kommt ein Statement, das kann ein Block 
sein, muss aber nicht.
Persönliche Seite #1495799
Lesenswert?
• ▲
▼
> Gehört die switch-ANweisung noch zum ELSE-Zweig?

Ja, das tut sie.

> Nein oder, weil dort
> meiner Meinung nach doch die {}-Umklammerung fehlt.

Die ist nur erforderlich, wenn ein kompletter Block abgegeben werden 
soll.


Es ist aber
1
if (a == 1)
2
  b = 2;
3
else
4
  b = 4;
gleichbedeutend mit
1
if (a == 1)
2
{
3
  b = 2;
4
}
5
else
6
{
7
  b = 4;
8
}


> Das gehört doch auf keinen Fall dem ANSI-C-Standard an?

Doch, das tut es, denn der else-Zweig ist nicht leer.
Gast #1495863
Lesenswert?
• ▲
▼
Weils Thema gerade soweit passt; mir sind auch schon 2 "seltsame" 
Konstrukte untergekommen, bei denen ich aber fast sicher bin, dass man 
hier was kürzen kann:
1
if (Vergleich)
2
{
3
  MachWas();
4
}
5
else
6
{
7
}

sowie
1
if (Vergleich)
2
{
3
  MachWas();
4
}
5
else if (!Vergleich)
6
{
7
  MachAnders();
8
}

Beim ersten kann man doch das gesamte else weglassen, beim 2. den 2. 
Vergleich. Oder gibts nen Grund, wieso man Code so schreibt bzw. 
schreiben sollte?
#1495887
Lesenswert?
• ▲
▼
Ab und zu mache ich auch sowas
1
  if( Vergleich )
2
    ;
3
  else {
4
    ...
5
  }

in der finalen Version wird das dann natürlich korrigiert :-)


---------------------------------------------------
1
if (Vergleich)
2
{
3
  MachWas();
4
}
5
else if (!Vergleich)
6
{
7
  MachAnders();
8
}

Da gibts auch Varianten dazu, die man häufiger sieht.
1
  if( x >= 100 )
2
    mach was
3
  else if( x < 100 )
4
    mach was anderes

Wenn x nicht größer/gleich 100 ist, dann kann es nur kleiner als 100 
sein. Der Vergleich bei else ist also überflüssig.

Oder
1
  unsigned char x = ....;
2

3
  if( x >= 0 && x < 100 )
4
    mach was;
5
  else if( x >= 100 && x < 150 )
6
    mach was anderes;
7
  else if( x >= 150 && x <= 255 )
8
    mach noch was
mindestens die Hälfte der Vergleiche sind überflüssig :-)
Die Grenzen bei 0 und 255 sollten klar sein.
Aber im ersten else if: an dieser Stelle MUSS x schon größer/gleich 100 
sein, ansonsten wäre man nie hier hin gekommen, sondern bereits beim 
ersten if gelandet.

--->
1
  unsigned char x = ....;
2

3
  if( x < 100 )
4
    mach was;
5
  else if( x < 150 )
6
    mach was anderes;
7
  else
8
    mach noch was
Gast #1495902
Lesenswert?
• ▲
▼
doch nämlich folgendes:

if (Vergleich)
{
  MachWas();
}
else if (!Vergleich)
{
  MachAnders();
}

als geschrieben:
void MachWas(void)
 {
  ....
  g_go = 0;
  ....
 }

void MachWasAnders(void)
 {
  ...
  g_go = !g_go;
  ...
 }
...
if (g_go)
{
  MachWas();
}
else if (!g_go)
{
  MachAnders();
}

...


bitte nciht verwechseln mit gogo girls ;)
Persönliche Seite #1495915
Lesenswert?
• ▲
▼
gast schrieb:
> doch nämlich folgendes:
>
> if (Vergleich)
> {
>   MachWas();
> }
> else if (!Vergleich)
> {
>   MachAnders();
> }

Nö.


> als geschrieben:
> (...)
>
> if (g_go)
> {
>   MachWas();
> }
> else if (!g_go)
> {
>   MachAnders();
> }
>

Wenn MachWas aufgerufen wird, wird der Else-Zweig nie aufgerufen, und 
also auch der enthaltene Vergleich nicht, und also MachAnders auch 
nicht.
Gast #1495970
Lesenswert?
• ▲
▼
Wenn der Vergleich Seiteneffekte hat, dann kommt bei zwei Vergleichen 
hintereinander nicht unbedingt das selbe Ergebnis heraus.


uint8_t nurEinmalFalsch()
{
    static uint8_t rueckgabe = 0;

    if (rueckgabe)
       return rueckgabe;
    rueckgabe++;
    return 0;
}
void blah()
{}
void blup()
{}

# define RICHTIG    1
void main (void)
{
if (nurEinmalFalsch() == RICHTIG)
{
    blah();
} else if ( ! (nurEinmalFalsch() == RICHTIG) )
{
    blup();
}
}

Oder jemand wollte noch einmal daran erinnern, wann der else Zweig 
ausgeführt wird, weil das if drei Seiten weiter oben stand.
Oder jemand konnte sich selbst nicht mehr erinnern, wann der else Zweig 
ausgeführt wird, weil das if drei Seiten weiter oben stand oder in der 
Nacht zuvor geschrieben wurde.
#1495974
Lesenswert?
• ▲
▼
horst schrieb:
> Wenn der Vergleich Seiteneffekte hat, dann kommt bei zwei Vergleichen
> hintereinander nicht unbedingt das selbe Ergebnis heraus.

Das sind aber keine 2 Vergleiche hintereinander.

Entweder wird der if Teil genommen oder es wird der else Zweig genommen. 
Was anderes gibt es nicht.
Wenn aber der if-Zweig betreten wird, dann ist damit automatisch der 
else Zweig bereits aus dem Rennen, egal ob dort dann noch eine weitere 
Abfrage erfolgt oder nicht.
Persönliche Seite #1496112
Lesenswert?
• ▲
▼
> Oder jemand wollte noch einmal daran erinnern, wann der else Zweig
> ausgeführt wird, weil das if drei Seiten weiter oben stand.
> Oder jemand konnte sich selbst nicht mehr erinnern, wann der else Zweig
> ausgeführt wird, weil das if drei Seiten weiter oben stand oder in der
> Nacht zuvor geschrieben wurde.

Für diese Fälle bietet C und auch C++ ein ganz raffiniertes Konstrukt:
Den Kommentar.
Gast #1496213
Lesenswert?
• ▲
▼
@ Stefan Ernst

switch(time)
{
   case:    //usw.
   default: //usw.
}

Das ist also nur 1 Anweisung?

Ich hatte gedacht, dass wäre schon ein Block...

Mal blöd gefragt, aber wann wird daraus ein Block?

Etwa so:

switch(time)
{
   case:    //usw.
   default: //usw.
}
i=1;
Gast #1496241
Lesenswert?
• ▲
▼
Solche saublöden Fragen entstehen immer dann, wenn man versucht, C 
anhand falscher Beispiele zu lernen, oder es halt so verkorkst 
beigebracht bekommt.

Es heißt:
1
if ( BEDINGUNG )
2
  ANWEISUNG
3
else
4
  ANWEISUNG
wobei der else-Teil wegfallen kann.

BEDINGUNG ist ein Ausdruck, ANWEISUNG eine Anweisung...son Zufall :-}

Eine Anweisung kann eines der folgenden sein:
1
AUSDRUCK ;
2
/* oder */
3
if...
4
/* oder */
5
switch...
6
/* oder for, while, do */
7
/* oder */
8
{ ANWEISUNG... }

(ja, etwas zusammengerafft)
Nun kannste dir deine If-Dinger zusammenstecken, wie LEGO-Klötze:
1
if (x)
2
  aaa();
3
else
4
  bbb();
5
  ccc();
6

7
/* äquivalent zu */
8

9
if (x) {
10
  aaa();
11
}
12
else {
13
  bbb();
14
}
15

16
ccc();
Gast #1496316
Lesenswert?
• ▲
▼
@Karl heinz Buchegger
> Das sind aber keine 2 Vergleiche hintereinander.

doch, schau mal:
1
#include <stdio.h>
2
#include <stdlib.h>
3

4
#define I i--
5

6
void foo(int i) {
7

8
  printf("%d : ",i);
9

10
  if (I >= 10)    printf("A");
11
  else if (I < 10) printf("B");
12

13
  printf(" : %d\n",i);
14
}
15

16
int main() {
17
  foo(8);
18
  foo(9);
19
  foo(10);
20
  foo(11);
21
}

das ganze liefert :
1
 8 : B : 6
2
 9 : B : 7
3
10 : A : 9
4
11 : A : 10

das 1. conditional wird immer ausgeführt - samt seiteneffekt, das 2. nur 
dann, wenn das 1. misslingt.
das kann ganz schön böse zum debuggen sein :-)

entstehen tut der käse mesitens aus so was, wenn die grenzen plötzlich 
gleich sind und keiner den code aufräumt:
1
if (i > 10 ) tu_was_großes();
2
else if (i<5) tu_was_kleines();
Gast #1496328
Lesenswert?
• ▲
▼
zwieblum schrieb:
> @Karl heinz Buchegger
>> Das sind aber keine 2 Vergleiche hintereinander.
> doch, schau mal:

Diese Argumentationsweise, bei der man das Ursprungsbeispiel so lange 
verbiegt, bis man irgendwie Recht zu haben scheint, geht mir gehoerig 
auf den Keks.
Gast #1496492
Lesenswert?
• ▲
▼
??? wieso geht's ums recht haben? das ursprungsbeispiel ist trivial, 
aber das versteckte problem nicht. nur weil's in C nicht üblich ist, 
dass vergleiche seiteneffekte haben können, heißt nicht, dass es nicht 
machbar ist. und wenn du die programmiersprache wechselst wird's sogar 
was ganz übliches ...
Gast #1497092
Lesenswert?
• ▲
▼
Es geht auch nicht mehr um's Ursprungsbeispiel, das wurde schon geklärt.

Es geht um das zweite Beispiel von Federtier. Dort können durchaus beide 
Vergleiche (die ifs, nicht die Blöcke danach) nach einander ausgeführt 
werden.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren