PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C++] logisches UND in Bedingungen


eXistence
2007-02-20, 08:18:02
Hi,
folgendes Beispiel:

if( a.aufwendigeMethode() > 0 && b == c )
{
doSomething();
}


Wenn die erste Bedingung false ergibt, wird dann die zweite überhaupt noch geprüft?

Hätte es dann einen perfomance-Vorteil, wenn man das umdreht und zuerst b == c prüft, weil dann die aufwendige Methode wirklich nur dann aufgerufen werden würde, wenn wenigstens schon die erste Bedingungen zutrifft?

Oder optimieren compiler sowas von selbst?

Shink
2007-02-20, 08:53:30
Tja, das hat man von der kryptischen C-Syntax...

&& entspricht "AND THEN" in z.B. ADA 95
& entspricht "AND".

Also:
&/AND => beides wird geprüft
&&/AND THEN => zweite Bedingung wird nur geprüft, wenn erste wahr ist.

Neomi
2007-02-20, 11:30:28
C/C++ nutzt die sogenannte "Shortcut Evaluation", wertet einen Ausdruck also nur dann aus, wenn es nötig ist. Mit Anweisungen, die Seiteneffekte haben, solltest du also aufpassen. Compiler dürfen die Reihenfolge übrigens nicht "optimieren", weil die Evaluierungsreihenfolge definiert ist. Anders wären z.B. solche Konstrukte nicht machbar:

if (HitTest (&ht) && (ht.Dist < MaxDist))
{
// ...
}

Diese beiden Codeblöcke hier sind prinzipiell identisch:

// kurze Schreibweise

if (a && b)
{
c;
}

// lange Schreibweise

if (a)
{
if (b)
{
c;
}
}

Expandable
2007-02-20, 13:29:24
Tja, das hat man von der kryptischen C-Syntax...

&& entspricht "AND THEN" in z.B. ADA 95
& entspricht "AND".

Also:
&/AND => beides wird geprüft
&&/AND THEN => zweite Bedingung wird nur geprüft, wenn erste wahr ist.

Nein! Das ist doch nur in Java so, oder? & in C++ ist bitweises und, && ist logisches und (wobei eben der zweite Teil nur geprüft wird, wenn der erste wahr ist), | und || analog.

patermatrix
2007-02-20, 13:44:58
& in C++ ist bitweises und, && ist logisches und (wobei eben der zweite Teil nur geprüft wird, wenn der erste wahr ist), | und || analog.
Korrekt.

Matrix316
2007-02-20, 14:11:06
Wobei man anmerken muss, dass bitweises & was ganz anderes ist als logisches &&.

Also bei & werden zwei werte verundet, während bei && einfach ein Vergleich stattfindet.

Nicht dass da jemand durcheinander kommt. ;)

patermatrix
2007-02-20, 14:17:55
Also bei & werden zwei werte bitweise verundet
SCNR ;)

Monger
2007-02-20, 14:18:59
Also bei & werden zwei werte verundet, während bei && einfach ein Vergleich stattfindet.

Machen wir doch spaßeshalber gleich mal ein Beispiel! ;)


(8 & 3) = b1000 & b0011 = b0000 = false
(8 && 3) = true & true = true // alle Werte ungleich null sind true

Hachja, ich liebe es...

ShadowXX
2007-02-20, 14:28:02
Wobei man anmerken muss, dass bitweises & was ganz anderes ist als logisches &&.

Also bei & werden zwei werte verundet, während bei && einfach ein Vergleich stattfindet.

Nicht dass da jemand durcheinander kommt. ;)
Schreib statt verrundet das nächste mal bitte, das da ganz einfach ein binäres Und zwischen den beiden Werten durchgeführt wird.

Ernsthaft gesagt ist der Begriff "verrundet" sogar völlig falsch, denn gerundet wird da gar nichts.

patermatrix
2007-02-20, 14:31:18
Ernsthaft gesagt ist der Begriff "verrundet" sogar völlig falsch, denn gerundet wird da gar nichts.
Deswegen sagt man ja auch verundet. Mit Runden hat das nichts zu tun. Das Pendant dazu wäre übrigens auch verodert. Oder, wenn man es ganz doll treiben will, z.B. auch vernort. Bei vernandet wirds dann langsam abenteuerlich.

Alles ganz normale Ausdrücke bei uns an der Uni. :ugly:

Wir sind übrigens ziemlich weit im OT...

btw, Monger

(8 & 3) = b1000 & b0011 = b0000 = false
(8 && 3) = true && true = true // alle Werte ungleich null sind true


Das UND bleibt logisch.

Xmas
2007-02-20, 14:40:31
Hätte es dann einen perfomance-Vorteil, wenn man das umdreht und zuerst b == c prüft, weil dann die aufwendige Methode wirklich nur dann aufgerufen werden würde, wenn wenigstens schon die erste Bedingungen zutrifft?
Ja. Theoretisch sollte man die Bedingungen nach ansteigendem Produkt aus Auswertungsaufwand und Wahrscheinlichkeit dass die Bedingung wahr (bei logischem oder: falsch) ist anordnen. Die Wahrscheinlichkeit muss vom Entwickler geschätzt werden. Bei ganz einfachen Bedingungen spart man aber häufig nichts wenn man sie überspringt, deswegen sollten diese eher links stehen.

Matrix316
2007-02-20, 14:44:25
Ernsthaft gesagt ist der Begriff "verrundet" sogar völlig falsch, denn gerundet wird da gar nichts.

Stimmt, denn verrundet ist was anderes als verundet. ;)

ShadowXX
2007-02-20, 14:49:49
Stimmt, denn verrundet ist was anderes als verundet. ;)
Also zu meiner Zeit auf der Uni hat man nicht so einen dämlichen Ausdruck dafür benutzt....bei "binäres und" weiß jeder was Sache ist und das ganze ist eindeutig.

Verundet hört sich wirklich grausam an...als ich das eben meinem Chef erzählte drehte er nur mit den Augen und meinte "das erklärt vieles......" (und das war nicht positiv gemeint).

Matrix316
2007-02-20, 14:52:05
Ich glaube auch nicht, dass sowas in Lehrbücher steht, aber bei uns sagten das sogar Professoren.

Shink
2007-02-20, 15:11:53
Nein! Das ist doch nur in Java so, oder? & in C++ ist bitweises und, && ist logisches und (wobei eben der zweite Teil nur geprüft wird, wenn der erste wahr ist), | und || analog.
Öh... haltet mich jetzt für blöd, aber: Was für einen Unterschied macht das denn bitte in Bedingungen?

& oder | bei boolschen Werten wertet doch in beiden Sprachen beide Seiten aus, oder?

Klar kann man & und | auch als Bit-Operator verwenden, aber da verhalten sich beide Sprachen gleich, oder?

Und &&/|| machen bei beiden Sprachen eine "Shortcut Evaluation" - was ist da der Unterschied? (ausser dass 8 und 3 als boolean eben nach C-Syntax "true" ergeben und man es sich bei Java erst casten müsste)

patermatrix
2007-02-20, 15:22:05
Ich glaube auch nicht, dass sowas in Lehrbücher steht, aber bei uns sagten das sogar Professoren.
Wenn man es kontextbezogen verwendet, finde ich es eigenlich ziemlich verständlich.
Ausserdem: Umschreibe mal den Ausdruck "A und B werden vernandet und anschliessend mit C verodert, das Ganze schliesslich mit D verundet", wie du das mündlich sagen würdest. Ich weiss, in der Informatik ist das (eher) praxisfern, aber in der Digitaltechnik... ;(

Matrix316
2007-02-20, 15:37:53
Öh... haltet mich jetzt für blöd, aber: Was für einen Unterschied macht das denn bitte in Bedingungen?

& oder | bei boolschen Werten wertet doch in beiden Sprachen beide Seiten aus, oder?

Klar kann man & und | auch als Bit-Operator verwenden, aber da verhalten sich beide Sprachen gleich, oder?


Natürlich werden bei & oder | beide Seiten "ausgewertet", weil es ja nur eine Operation ist.

bei sowas if (2>4 & 3<5) ist der erste ausdruck true und das wird "verundet" mit dem zweiten ausdruck der ebenfalls true ist....(bzw. wird glaube ich bei C bei Operationen hinten angefangen)

Ok, so gesehen, haste dann schon recht. ;):rolleyes:

ShadowXX
2007-02-20, 15:38:33
Wenn man es kontextbezogen verwendet, finde ich es eigenlich ziemlich verständlich.
Ausserdem: Umschreibe mal den Ausdruck "A und B werden vernandet und anschliessend mit C verodert, das Ganze schliesslich mit D verundet", wie du das mündlich sagen würdest. Ich weiss, in der Informatik ist das (eher) praxisfern, aber in der Digitaltechnik... ;(
A NAND B, anschließend ODER C anschließend UND D.....

Wenn wir über das gleiche Thema reden, weiß jeder was gemeint ist....

Langform:
A mittels binären NAND mit B verknüpfen dann ein binäres ODER mit C drauf durchführen um anschließend das ganze mit einem binären UND mit D zu verknüpfen.
(Zumindest wurde so früher bei mir auf der Uni das ganze gesprochen)

Monger
2007-02-20, 15:41:13
& oder | bei boolschen Werten wertet doch in beiden Sprachen beide Seiten aus, oder?

Eben nicht. Wenn bei && der erste Ausdruck schon nicht wahr ist, wird der zweite erst gar nicht mehr geprüft. Zumindest in C++, in Java dagegen nicht. (siehe unten)


Klar kann man & und | auch als Bit-Operator verwenden, aber da verhalten sich beide Sprachen gleich, oder?

Auch nicht. In C++ ist eben & der Bit Operator. Diese Unterscheidung ist notwendig, weil in C++ eine Zahl sowohl ein booleescher Wert als auch eine Zahl sein kann. In Java gibt es diese Doppeldeutigkeit eben nicht.


Und &&/|| machen bei beiden Sprachen eine "Shortcut Evaluation" - was ist da der Unterschied? (ausser dass 8 und 3 als boolean eben nach C-Syntax "true" ergeben und man es sich bei Java erst casten müsste)
Wie gesagt: C++ macht grundsätzlich eine Shortcut Evaluation, Java eben nicht.
Und du kannst in Java nicht von int auf boolean casten.

ShadowXX
2007-02-20, 15:45:11
Eben nicht. Wenn bei & der erste Ausdruck schon nicht wahr ist, wird der zweite erst gar nicht mehr geprüft. Zumindest in C++, in Java dagegen nicht. (siehe unten)

Ähhh nein....&& ist der logische Operator, auf den grundsätzlich eine Shortcut Evaluation durchgeführt wird.


Auch nicht. In C++ ist eben && der Bit Operator. Diese Unterscheidung ist notwendig, weil in C++ eine Zahl sowohl ein booleescher Wert als auch eine Zahl sein kann. In Java gibt es diese Doppeldeutigkeit eben nicht.

Ähh...andersherum: & ist der binäre Operator, && der Logische.


Wie gesagt: C++ macht mit & grundsätzlich eine Shortcut Evaluation, Java eben nicht.
Und du kannst in Java nicht von int auf boolean casten.
Nein, C++ macht bei && grundsätzlich eine Shortcut Evaluation.

Matrix316
2007-02-20, 15:45:20
Meinst du nicht umgekehrt? && ist der logische und & der Bit Operator? :|

edit: zwei Dumme...;)

Monger
2007-02-20, 15:48:04
Ähhh nein....&& ist der logische Operator

Ähh...andersherum: & ist der binäre Operator, && der Logische.

Nein, C++ macht bei && grundsätzlich eine Shortcut Evaluation.

ARGH!!!
Ich bring das jedes mal durcheinander!


meinPost != meinPost;


Besser so? ;)

Edit:
Nicht verwirrt sein wenn ich jetzt meinen vorigen Post editiere, sonst stifte ich noch mehr Verwirrung.

ShadowXX
2007-02-20, 16:01:21
meinPost != meinPost;

Besser so? ;)

Juppss....war auch nicht bös gemeint.

Überigens ist dieser Satz von dir eigentlich das wichtigeste an der ganze Sache (Hab mal das eine "&" weggemacht):

Auch nicht. In C++ ist eben & der Bit Operator. Diese Unterscheidung ist notwendig, weil in C++ eine Zahl sowohl ein booleescher Wert als auch eine Zahl sein kann. In Java gibt es diese Doppeldeutigkeit eben nicht.

Den "&" Operator (genauso wie "|") benutzt man in C/C++ eigentlich auch nur um binäre Operationen oder Ausmaskieren durchzuführen, so in der Art wie:
If((Ergebnis | Konstante) == Konstante2)
{
// Code
}

Da kann man dann auch ganz gut sehen, das das ganze nicht das gleiche wie das logische Oder ist, denn if((Ergebnis || Konstante) == Konstante2) würde ein ganz anderes Laufzeitverhalten hervorrufen.

Oder eben zum "Rechnen":
DWORD sytle = WS_BORDER | WS_CHILD |........

PH4Real
2007-02-20, 17:27:29
Eben nicht. Wenn bei && der erste Ausdruck schon nicht wahr ist, wird der zweite erst gar nicht mehr geprüft. Zumindest in C++, in Java dagegen nicht.[...]


Falsch. Natürlich macht Java eine Short-circuit Evaluation:

// Wenn node null ist, wird getSomething() nicht aufgerufen
// -> While Block wird nicht betreten
while (node != null && node.getSomething() > irgendwas) {
}


// Wenn node null ist -> NullPointerException
while (node != null & node.getSomething() > irgendwas) {
}

Monger
2007-02-20, 17:31:34
Falsch. Natürlich macht Java eine Shortcut Evaluation:


Drücke ich mich wirklich so undeutlich aus? In Java kann man zwischen beiden Varianten wählen, in C++ wird NUR die Shortcut Evaluation genutzt.

Vielleicht habe ich ja heute wirklich Sand im Sprachgetriebe...

PH4Real
2007-02-20, 17:36:54
Drücke ich mich wirklich so undeutlich aus? In Java kann man zwischen beiden Varianten wählen, in C++ wird NUR die Shortcut Evaluation genutzt.

Vielleicht habe ich ja heute wirklich Sand im Sprachgetriebe...

Ich habe bestimmt 3mal deinen Ausschnitt gelesen, aber so habe ich ihn nie verstanden :D.

Shink
2007-02-20, 18:42:08
Drücke ich mich wirklich so undeutlich aus? In Java kann man zwischen beiden Varianten wählen, in C++ wird NUR die Shortcut Evaluation genutzt.

Vielleicht habe ich ja heute wirklich Sand im Sprachgetriebe...
Meinst du das ernst:

(isTricky() & isBroken() & isGone())
und
(isTricky() && isBroken() && isGone())

liefert in Java das selbe Ergebnis und in C/C++ nicht, wenn die Methoden einen Boolean-Wert (oder von mir aus in C 0 oder 1) zurückliefern?

Oder geht es vielleicht darum, dass ich in C/C++ auch einen Integer-Wert zurückliefern kann und damit sowohl & und && machen kann, was sich anders verhält, während man in Java in so einem Fall nur & machen dürfte, ausser man ersetzt seine Rückgabewerte val durch (val>0), was wieder das selbe wär wie in C?

(Schöner langer Satz. Langsam kommen wir weiter...)

Monger
2007-02-20, 19:39:13
Oder geht es vielleicht darum, dass ich in C/C++ auch einen Integer-Wert zurückliefern kann und damit sowohl & und && machen kann, was sich anders verhält, während man in Java in so einem Fall nur & machen dürfte, ausser man ersetzt seine Rückgabewerte val durch (val>0), was wieder das selbe wär wie in C?

Ich kenn mich mit C++ nicht so aus, aber afaik arbeitet C++ an der Stelle ganz genauso wie C, und kennt eigentlich gar keinen Bool-Typen. Das ist nur ein Compiler Hack, der im Endeffekt aus einem "true" ein "b11111111" macht. Und da bleibt es sich dann auch gleich, ob ich bitweise oder logisch miteinander verknüpfe, weil 255 & 255 sind halt immer noch 255.

Bizarr wird es wie gesagt dann, wenn ich beliebige Integer Werte so rum oder anders rum verknüpfe. Da können dann unerwartete Effekte rauskommen, und es kann auch nie ein Typenkonflikt auftreten, weil int und bool in Wahrheit der selbe Typ sind.

In Java ist es wie gesagt vom Typ abhängig, was das "&" bedeutet.



boolean y = isRight() & isReady() // Ergebnis: false, ohne Short circuit evaluation
boolean y = isRight() && isReady() // Ergebnis: false, mit Short circuit evaluation
int x = 5 & 4; // Ergebnis: 4
int x = 5 && 4; // falsch, gibt es nicht!!!

Xmas
2007-02-20, 20:00:33
bei sowas if (2>4 & 3<5) ist der erste ausdruck true und das wird "verundet" mit dem zweiten ausdruck der ebenfalls true ist....(bzw. wird glaube ich bei C bei Operationen hinten angefangen)
Welcher Ausdruck hier zuerst ausgewertet wird ist bei C/C++ nicht festgelegt.