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.
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.
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.
> 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.
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
elseif(!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?
in der finalen Version wird das dann natürlich korrigiert :-)
---------------------------------------------------
1
if(Vergleich)
2
{
3
MachWas();
4
}
5
elseif(!Vergleich)
6
{
7
MachAnders();
8
}
Da gibts auch Varianten dazu, die man häufiger sieht.
1
if(x>=100)
2
machwas
3
elseif(x<100)
4
machwasanderes
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
unsignedcharx=....;
2
3
if(x>=0&&x<100)
4
machwas;
5
elseif(x>=100&&x<150)
6
machwasanderes;
7
elseif(x>=150&&x<=255)
8
machnochwas
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.
--->
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.
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.
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.
> 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.
@ 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;
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:
@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:
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.
??? 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 ...
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.