Forum: Compiler & IDEs if und UND-verknüpfte Bedignungen


von Blub (Gast)


Lesenswert?

Hallo zusammen!

Was ist denn besser? Eine Latte von UND-verknüpften Bedingungen -die 
auch Rückgabewerte von Funktionsaufrufen beinhalten-, in einer 
if-Abfrage und lieber ineinander mit aufsteigender Komplexität 
verschachtelt, um Rechenzeit zu sparen?

Danke & Grüße
Blub

von Blub (Gast)


Lesenswert?

Blub schrieb:
> in einer if-Abfrage und lieber ineinander

Äh! Zuviel "UND"! ;-)
Sollte natürlich "ODER" lauten:
"...in einer if-Abfrage, ODER lieber ineinander ..."

von Stefan P. (form)


Lesenswert?

Kannst Du ruhig hintereinander schreiben. Da von links nach rechts 
abgearbeitet wird, und bei dem ersten false eh abgebrochen wird.
Um Rechenzeit zu sparen am besten die Bedingungen die am 
häufigsten/schnellsten false liefern ganz nach links schreiben.

: Bearbeitet durch User
von teze (Gast)


Lesenswert?

Richtig, beides ist (zumindest in C und einigen anderen Sprachen) 
äquivalent. Immer daryn denken falls eine der aufgerufenen Funktionen 
gewünschte Seiteneffekte hat.

von Blub (Gast)


Lesenswert?

Stefan P. schrieb:
> Kannst Du ruhig hintereinander schreiben. Da von links nach rechts
> abgearbeitet wird, und bei dem ersten false eh abgebrochen wird.
> Um Rechenzeit zu sparen am besten die Bedingungen die am
> häufigsten/schnellsten false liefern ganz nach links schreiben.

Super! Danke! Die Antwort, die ich gebraucht und erhofft habe! ;-)

von user (Gast)


Lesenswert?

in C ist die Auswertungsreihenfolge der Argumente undefiniert

von J. F. (Firma: Père Lachaise) (rect)


Lesenswert?

user schrieb:
> in C ist die Auswertungsreihenfolge der Argumente undefiniert

In C ist die Reihenfolge definiert. Grob gesagt: sie erfolgt immer 
links-nach-rechts ausser bei:
1
* Operationen (! ~ ++ --)
2
* ?:
3
* Zuweisung (= += -= *= /= %= &= ^= |= <<= >>=)

Mehr: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

: Bearbeitet durch User
von MaWin. (nur echt mit Punkt) (Gast)


Lesenswert?

user schrieb:
> in C ist die Auswertungsreihenfolge der Argumente undefiniert

Es geht hier um:
https://en.wikipedia.org/wiki/Short-circuit_evaluation

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Blub schrieb:

> Was ist denn besser?

Übrigens kann man auch das Ergebnis von boolschen Operatoren in einer 
Variablen zwischenspeichern, wenn das ggf. die Lesbarkeit erhöht.
1
  bool first_parameter_valid  = p1 >= 4 && p1 < 20;
2
  bool second_parameter_valid = p2 >= 3 && p2 < 99;
3
4
  if ( first_parameter_valid && second_parameter_valid )
5
    ...

mfg Torsten

von A. S. (Gast)


Lesenswert?

Torsten R. schrieb:
> Übrigens kann man auch das Ergebnis von boolschen Operatoren in einer
> Variablen zwischenspeichern, wenn das ggf. die Lesbarkeit erhöht.
1
>   bool first_parameter_valid  = p1 >= 4 && p1 < 20;
2
>   bool second_parameter_valid = p2 >= 3 && p2 < 99;
3
> 
4
>   if ( first_parameter_valid && second_parameter_valid )
5
>     ...

das erhöht aber kaum die Lesbarkeit gegenüber
1
    if( (p1>=4 && p1<20) && (p2>=3 && p2<99) )
2
        ...

Dann lieber an den Rangeprüfungen arbeiten:
1
    if(   inrange(p1, 4, 19) 
2
       && inrange(p2, 3, 98)
3
      )
4
        ...

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Achim S. schrieb:

> das erhöht aber kaum die Lesbarkeit gegenüber

Achim, das war nur ein Beispiel! ;-)

von Oke (Gast)


Lesenswert?

lesbarer wird es noch in C++ mit Classen und Templates
1
#include "Range.hpp"
2
Range<int> LimitP1(4,19);
3
Range<int> LimitP2(3,98);
4
5
6
7
.
8
.
9
.
10
if (LimitP1.InRange(p1) && LimitP2.InRange(p2))
11
{
12
   ...
13
}

lesbarer wäre noch (pseudo code)
1
if (p1.InRange(LimitP1) && p2.InRange(LimitP2))

von A. S. (Gast)


Lesenswert?

Torsten R. schrieb:
> Achim, das war nur ein Beispiel! ;-)

Das verstehe ich, Torsten, und mit Deinem Beispiel bist Du konform zu 
Lehrbüchern für guten Code. Vor allem, wenn man McCabe und anderen 
Metriken folgt, ebenso TTD (Unittests), und vorwiegend orthogonale, 
unabhängige Modulen von je ~1000 Zeilen programmiert.

Sobald man größere Projekte hat, mit Modulen von mehrern 1000 Zeilen und 
einer durch die reale Welt intensiven faktische Verknüpfung, dann rückt 
ein Problem in den Vordergund: Die Lesbarkeit (Geschwindigkeit) des 
Quellcodes. Und hier die Begrenzung von Token sowie die Anzahl der 
Indirektionsebenen.

Hier als Beispiel: Diese if-Schleife wurde durchlaufen, und jemand fragt 
sich, wieso. Wenn dort alle 100 Abfragen direkt untereinander stehen, 
kann er diese (mit dem Auge) scannen und ggf. direkt mit seiner IDE 
nähere Informatione zu p1 oder p2 bekommen. Bei first_parameter_valid 
muss er dazu erst dorthin springen.

Viele Funktionen, die Mc-Cabe senken oder Unittests vereinfachen sollen, 
erschweren real die Lesbarkeit und machen den Code (durch weggekapselten 
Kontext) unsicherer.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Torsten R. schrieb:
> Übrigens kann man auch das Ergebnis von boolschen Operatoren in einer
> Variablen zwischenspeichern, wenn das ggf. die Lesbarkeit erhöht.

Dann fällt aber (zumindest teilweise) die genannte short-circuit
evaluation weg.  Bei deinen einfachen Variablenabfragen mag das
egal sein, aber wenn zwischendrin eine komplexere Funktion aufgerufen
wird, berechnest du ggf. ein Ergebnis, welches für die Katz' ist.

Noch schlimmer, das Ergebnis könnte undefiniert sein oder eine
Speicherschutzverletzung bringen.  Überleg' dir mal, wie du das
mit dem Zwischenspeichern in Variablen hier machst bzw. was dann
passiert:
1
   if (ptr != NULL && eval_data(ptr->data) != 42) {
2
      // …
3
   }

Danach weißt du, warum man eine wohldefinierte short-circuit
evaluation in einer Sprache braucht.  (Pascal hatte sie zumindest
im ersten Standard nicht, sondern hat es dem Compiler überlassen.
In der Folge musste man dann immer zweimal if verschachteln.)

: Bearbeitet durch Moderator
von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Jörg W. schrieb:

> Überleg' dir mal, wie du das
> mit dem Zwischenspeichern in Variablen hier machst bzw. was dann
> passiert:
>
>
1
>    if (ptr != NULL && eval_data(ptr->data) != 42) {
2
>       // …
3
>    }
4
>

Na, der "übliche" Weg ist dann, den Ausdruck schrittweise zu entwickeln:
1
const bool data_exists = ptr != 0;
2
const bool not_42      = data_exists && eval_data(ptr->data) != 42;


versteht mich nicht falsch, ich sage nicht, dass diese der einzige, 
wahre Weg ist! Ich wollte nur darauf hinweisen, dass dies ein Mittel 
sein kann, die Lesbarkeit zur erhöhen (Zitat: "wenn das ggf. die 
Lesbarkeit erhöht.")

Und ja, natürlich muss man short circuit berücksichtigen. Das muss man 
aber auch, wenn man den gesamten Ausdruck in einem hinschreibt.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Torsten R. schrieb:
> const bool not_42      = data_exists && eval_data(ptr->data) != 42;

Das aber setzt zwingend funktionierende short-circuit evaluation 
voraus, sonst knallt's, wenn ptr dereferenziert wird, um "eval_data" 
aufzurufen.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Rufus Τ. F. schrieb:
> Torsten R. schrieb:
>> const bool not_42      = data_exists && eval_data(ptr->data) != 42;
>
> Das aber setzt zwingend funktionierende short-circuit evaluation
> voraus, sonst knallt's, wenn ptr dereferenziert wird, um "eval_data"
> aufzurufen.

Oh mann, ließt den hier niemand mehr, sondern stürzt sich nur noch auf 
das letzte Posting?

Sorry, aber ich bin jetzt raus.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Keine Ahnung, was "leßen" sein soll - aber in einer Diskussion, wo um 
die Notwendigkeit oder nicht-Existenz der "short circuit evaluation" 
gestritten wird ... nehme ich den Thread vermutlich anders wahr als Du.

von Rolf M. (rmagnus)


Lesenswert?

Rufus Τ. F. schrieb:
> Keine Ahnung, was "leßen" sein soll - aber in einer Diskussion, wo um
> die Notwendigkeit oder nicht-Existenz der "short circuit evaluation"
> gestritten wird ... nehme ich den Thread vermutlich anders wahr als Du.

Naja, so ganz nachvollziehen kann ich den Sinn deines Postings aber auch 
nicht. Nachdem Torsten meinte, dass man
1
   if (ptr != NULL && eval_data(ptr->data) != 42) {
z.B. auch durch
1
const bool data_exists = ptr != 0;
2
const bool not_42      = data_exists && eval_data(ptr->data) != 42;
ersetzen könnte, meinst du, dass das aber zwingend short-circuit 
evaluation benötigt. Das hat aber das Original auch schon. Außerdem 
hatte er das in seinem Posting schon selber explizit erwähnt:

Torsten R. schrieb:
> Und ja, natürlich muss man short circuit berücksichtigen. Das muss man
> aber auch, wenn man den gesamten Ausdruck in einem hinschreibt.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dann sind wir ja immerhin alle einer Meinung. Ist doch gut so.

von Dumdi D. (dumdidum)


Lesenswert?

und hier das ärgerliche: beim überladenen && (in c++) gibt es wohl keine 
short-circuit evaluation.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Dumdi D. schrieb:
> und hier das ärgerliche: beim überladenen && (in c++) gibt es wohl keine
> short-circuit evaluation.

Wozu brauchst du das? Der Short-Circuit macht ja nur dann Sinn, wenn die
Operanden wie boolesche Werte behandelt werden können. Dann kannst du
für den neuen Datentyp aber auch einfach eine Konvertierungsfunktion
nach bool (operator bool()) schreiben und die normale &&-Operation mit
Short-Circuit verwenden.

Oder nimm Haskell ;-)

Da wird defaultmäßig lazy evaluiert, was das Short-Circuiting innerhalb
einer selbstgeschriebenen Funktion automatisch nach außen trägt. Solche
Funktonen wie && und || sind dort überhaupt nichts Spezielles und auch
nicht auf boolesche Werte beschränkt.

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.