Forum: Mikrocontroller und Digitale Elektronik C: Bedingte Anweisung "if"


von Georg M. (g_m)


Lesenswert?

Was ist der Unterschied zwischen
1
 if(a > b && c > d)
2
 {
3
   . . . . . . . .
4
 }
und
1
 if(a > b)
2
 {
3
   if(c > d)
4
   {
5
     . . . . . . . .
6
   }
7
 }
?

von Michael B. (laberkopp)


Lesenswert?

Georg M. schrieb:
> Was ist der Unterschied

Kompiliert in Maschinenbefehle kommt dasselbe raus

Beim zweiten kannst du mehr else-Zweige nutzen.

von Bruno V. (bruno_v)


Lesenswert?

Ist beides wirklich das gleiche. Auch in der Ausführung:
Wenn a>b, dann wird c>d nicht mehr abgefragt/ausgeführt.
a>b wird garantiert vor c>d abgefragt.

Bei einfachen Zahlen/Variablen ist das egal. Wenn c oder d jedoch 
Makro/Funktion/HW-Register sind, dann kann das wichtig sein. Und beide 
Versionen verhalten sich exakt gleich (solange a,b,c oder d kein Makro 
ist, dass irgendeine ganz andere Sache macht)

von Obelix X. (obelix)


Lesenswert?

Bruno V. schrieb:
> Wenn a>b, dann wird c>d nicht mehr abgefragt/ausgeführt.

Da fehlt das Wörtchen "nur" und das "nicht" ist zu viel.

Nur wenn a>b, dann wird c>d ausgewertet.

Bei ODER "||" wäre dein Satz richtig. Gilt dann aber nicht mehr für den 
zweiten Snipped.

: Bearbeitet durch User
von Wastl (hartundweichware)


Lesenswert?

Obelix X. schrieb:
> Nur wenn a>b, dann wird c>d ausgewertet.

Ist die Abarbeitung ohne Klammerung nicht von rechts nach links?

von Obelix X. (obelix)


Lesenswert?

Warum sollte? Würde Michael und Bruno widersprechen. Und der Satz von 
Bruno wäre dann immer noch nicht richtiger.

: Bearbeitet durch User
von Wastl (hartundweichware)


Lesenswert?

Wenn die Abarbeitung von rechts nach links geschieht (ich
weiss es nicht ob es so ist) dann würde erst c>d ausgewertet
und ggf. a>b nicht.

Obelix X. schrieb:
> Nur wenn a>b, dann wird c>d ausgewertet.

von Axel S. (a-za-z0-9)


Lesenswert?

Georg M. schrieb:
> Was ist der Unterschied zwischen

[schnipp]

Logisch ist es das gleiche. Ob der gleiche Maschinencode dabei 
herauskommt, hängt vom Compiler und der Optimierungstufe ab.

Variante 1 ist aber kompakter und IMHO auch leichter lesbar.

von Matthias T. (matthiasthiele)


Lesenswert?

Wie bereits geschrieben: in vielen Fällen wird der Compiler den gleichen 
Code erzeugen. Im Compiler Explorer kannst Du Dir das auch anzeigen 
lassen.

von Bruno V. (bruno_v)


Lesenswert?

Obelix X. schrieb:
> Nur wenn a>b, dann wird c>d ausgewertet.

Sorry. Natürlich völlig richtig.

Genauso wie im if-Schachtelcode.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Georg M. schrieb:
> Was ist der Unterschied zwischen

Was ist der Kern/Grund deiner Frage?

Warum ich das Frage:
Ein solche Frage hätte ich evtl. von einem Einsteiger erwartet.
Nicht von jemandem mit bald 4000 Postings auf dem Buckel.
Da steckt also wohl was anderes dahinter....

von Harald K. (kirnbichler)


Lesenswert?

Wastl schrieb:
> Ist die Abarbeitung ohne Klammerung nicht von rechts nach links?

Nein.
1
int *p;
2
3
p = NULL;
4
5
6
if (p && *p == 4)
7
{
8
}
Würde von rechts nach links ausgewertet, stürzte das mit einer 
Nullpointer-Exception ab.
Tut es aber nicht, da eben von links nach rechts ausgewertet wird.

von Sebastian W. (wangnick)


Lesenswert?

Harald K. schrieb:
> Tut es aber nicht, da eben von links nach rechts ausgewertet wird.

Genau. Man sollte Assoziativität und Abarbeitungsreihenfolge nicht in 
einen Topf werfen: "Precedence and associativity are independent from 
order of evaluation."

https://en.cppreference.com/w/c/language/operator_precedence

https://en.cppreference.com/w/c/language/eval_order

LG, Sebastian

von Tilo R. (joey5337) Benutzerseite


Lesenswert?

Harald K. schrieb:
> Wastl schrieb:
>> Ist die Abarbeitung ohne Klammerung nicht von rechts nach links?
>
> Nein.
>
>
1
> int *p;
2
> 
3
> p = NULL;
4
> 
5
> 
6
> if (p && *p == 4)
7
> {
8
> }
9
>
>
> Würde von rechts nach links ausgewertet, stürzte das mit einer
> Nullpointer-Exception ab.
> Tut es aber nicht, da eben von links nach rechts ausgewertet wird.

Thou shalt not follow the NULL pointer, for chaos and madness await thee 
at its end!

Etwas ausprobieren ist keine valide Taktik in C, weil es sein kann, dass 
du dabei undefined behaviour nutzt.
Der Compiler geht davon aus, dass der Programmierer weiß was er tut. 
Dein Code darf kein undefined behaviour enthalten und der Compiler ist 
frei, unter dieser Annahme beliebige Optimierungen durchzuführen. Es 
kann sein, dass das mit deinem aktuellen Compiler und den aktuellen 
Einstellungen funktioniert und der Code genau das macht, was du 
erwartest. Genau so gut kann das irgendwann in der Zukunft aber auch 
nicht mehr so sein. Dann hast du einen fiesen Fehler in gut 
abgehangenem, getestetem und seit Jahren zuverlässigem Code.

(Das war nur als allgemeine Warnung gedacht, dein Beispiel ist ok. Ich 
gehe sogar davon aus, dass für genau diesen &&-Anwendungsfall die 
Compiler eine optimierte Implementierung haben.)

von Cyblord -. (cyblord)


Lesenswert?

Tilo R. schrieb:
> (Das war nur als allgemeine Warnung gedacht, dein Beispiel ist ok.

Und deshalb ist dein ganzes Post Unsinn.

Es ist normal dass man Pointer auf NULL testet bevor man drauf zugreift. 
Und die Reihenfolge ist eben genau festgelegt und kein Zufall und kein 
undefined behaviour.

: Bearbeitet durch User
von Tilo R. (joey5337) Benutzerseite


Lesenswert?

Cyblord -. schrieb:
> Tilo R. schrieb:
>> (Das war nur als allgemeine Warnung gedacht, dein Beispiel ist ok.
>
> Und deshalb ist dein ganzes Post Unsinn.
sehe ich anders.
>
> Es ist normal dass man Pointer auf NULL testet bevor man drauf zugreift.
Richtig, ich habe nichts gegenteiliges behauptet.

> Und die Reihenfolge ist eben genau festgelegt und kein Zufall und kein
> undefined behaviour.
Richtig, ich habe nichts gegenteiliges behauptet.

Tilo R. schrieb:
> Etwas ausprobieren ist keine valide Taktik in C
Das ist meine Kernaussage. Imho auch richtig, ich habe sie sogar 
begründet.

von Rbx (rcx)


Lesenswert?

1. Klammereinsparung
2. Besser von außen sichtbar, außer man hat viel mit Lisp zu tun ;)

von Cyblord -. (cyblord)


Lesenswert?

Tilo R. schrieb:
>> Etwas ausprobieren ist keine valide Taktik in C
> Das ist meine Kernaussage. Imho auch richtig, ich habe sie sogar
> begründet.

Testen auf etwas ist kein "ausprobieren".

Dein Post ist reine Klugscheißen zu einem Problem was es im zitierten 
Code nicht gibt.

: Bearbeitet durch User
von Harald K. (kirnbichler)


Lesenswert?

Tilo R. schrieb:
> Ich gehe sogar davon aus, dass für genau diesen &&-Anwendungsfall
> die Compiler eine optimierte Implementierung haben.

Das ist die "short circuit evaluation", die gibt es genauso beim 
logischen Oder.
1
int *p;
2
3
p = NULL;
4
5
if (!p || *p)
6
{
7
}
Auch das stürzt nicht ab, weil die Auswertung des logischen Oder nach 
dem ersten zutreffenden Element (hier: !p) abgebrochen wird.

https://de.wikipedia.org/wiki/Kurzschlussauswertung
https://en.wikipedia.org/wiki/Short-circuit_evaluation

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Paar Anmerkungen zur Shortcut-Evaluation:

Wenn der zweite Teilausdruch in a && b keine Seiteneffekte hat, dann 
darf der Compiler (bzw. der von ihm erzeugte Code) den Ausdruck 
auswerten, falls günstig. Beispiel:
1
void fun (void);
2
3
void call_fun (int a)
4
{
5
    if (a >= 10 && a <= 20)
6
        fun();
7
}
wird mit avr-gcc zu:
1
call_fun:
2
        sbiw r24,10
3
        sbiw r24,11
4
        brsh .L1
5
        rjmp fun
6
.L1:    ret
Man kann also die Teilausdrücke nicht mehr bestimmten 
Instruktion(sfolg)en zuordnen.

Nochn Hinweis zu C++: Shortcut Evaluation wird nicht auf überladene 
Operatoren && und || angewandt.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.
Lade...