mikrocontroller.net

Forum: PC-Programmierung IF-ELSE ohne Anweisung im else-Zweig


Autor: Sven Schol (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
if (a == 1)
  b = 2;
else
  b = 4;
gleichbedeutend mit
if (a == 1)
{
  b = 2;
}
else
{
  b = 4;
}


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

Doch, das tut es, denn der else-Zweig ist nicht leer.

Autor: Federtier (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
if (Vergleich)
{
  MachWas();
}
else
{
}

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

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?

Autor: Erik W. (exor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm sieht mir fast wie automatisch generierter code aus ner state-machine 
oder so aus

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ab und zu mache ich auch sowas
  if( Vergleich )
    ;
  else {
    ...
  }

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


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

Da gibts auch Varianten dazu, die man häufiger sieht.
  if( x >= 100 )
    mach was
  else if( x < 100 )
    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
  unsigned char x = ....;

  if( x >= 0 && x < 100 )
    mach was;
  else if( x >= 100 && x < 150 )
    mach was anderes;
  else if( x >= 150 && x <= 255 )
    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.

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

  if( x < 100 )
    mach was;
  else if( x < 150 )
    mach was anderes;
  else
    mach noch was

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;)

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: horst (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sven Scholl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
if ( BEDINGUNG )
  ANWEISUNG
else
  ANWEISUNG
wobei der else-Teil wegfallen kann.

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

Eine Anweisung kann eines der folgenden sein:
AUSDRUCK ;
/* oder */
if...
/* oder */
switch...
/* oder for, while, do */
/* oder */
{ ANWEISUNG... }

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

/* äquivalent zu */

if (x) {
  aaa();
}
else {
  bbb();
}

ccc();



Autor: zwieblum (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl heinz Buchegger
> Das sind aber keine 2 Vergleiche hintereinander.

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

#define I i--

void foo(int i) {

  printf("%d : ",i);

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

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

int main() {
  foo(8);
  foo(9);
  foo(10);
  foo(11);
}

das ganze liefert :
 8 : B : 6
 9 : B : 7
10 : A : 9
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:
if (i > 10 ) tu_was_großes();
else if (i<5) tu_was_kleines();

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: zwieblum (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ...

Autor: horst (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.