2012-11-01 9 views
5

Von den folgenden, welche ist die bevorzugte Art, Dinge zu tun, und warum? Gibt es bestimmte Situationen, in denen es einen Unterschied macht, unter der Annahme, dass die Funktionsleiste() zu keinem Zeitpunkt den Wert Null annimmt?Was ist der geeignetste Weg, um eine Variable in einer if-Anweisung zuzuweisen und zu testen?

Fall 1: Testen Sie den Wahrheitswert beider

Bedingungen
if ((foo = bar()) && foo < 0) 
    error(); 

Fall 2: Test nur die Variablen zugewiesen

if ((foo = bar()) < 0) 
    error(); 
+0

Für diejenigen, die dies finden und Perl verwenden, ist das Idiom 'foo = bar() oder error();'. Dies kann auch in C gemacht werden, aber es ist nicht üblich und kann verwirren: '(foo = bar()) || error(); '- Perls Zuweisung hat eine höhere Priorität als' || ', aber in C ist es umgekehrt. –

+0

@PhilH Es wird allgemein als schlechter Stil angesehen, bedingte Nebenwirkungen als rechten Operanden einer booleschen Operation einzuschließen (MISRA-C 12.4). Und Ihr Code funktioniert nur, wenn error() etwas zurückgibt. Also versuchen Sie das nicht in C. – Lundin

+0

Guter Punkt auf der Rückkehranforderung; Ich nehme an, in Perl gibt es keine solche Überprüfung und Fehler() wird immer ausgeführt. –

Antwort

14

Der bevorzugte Weg ist, sie zu trennen:

foo = bar(); 
if (foo < 0) 
    error(); 

Edit: Dies ist der bessere Weg für die Lesbarkeit und die Vermeidung von Fehlern, wie im ersten Fall:

if (foo = bar() && foo < 0) 
    error(); 

, die wahrscheinlich sein sollte:

if ((foo = bar()) && foo < 0) 
    error(); 
+0

Hat dieser Weg eine bessere Leistung? Oder ist es nur zur besseren Lesbarkeit bevorzugt? –

+5

Während ich nicht sagen kann, ob es einen Unterschied in irgendeinem Compiler gibt, sollte C-Coder sich nicht darum kümmern. Dies ist ein besserer Weg sowohl für die Lesbarkeit als auch zur Vermeidung von Fehlern. (wie im OP ersten Fall) – MByD

+0

Es sollte absolut keinen Unterschied in der Leistung sein. In beiden Fällen lautet der Maschinencode: exce bar(), speichern Sie das Ergebnis vorübergehend irgendwo, speichern Sie es dann in foo und verzweigen Sie, wenn foo kleiner als Null ist. – Lundin

2

Die erste ist einfach falsch. Aufgrund von Vorrangregeln erhalten Sie:

if (foo = (bar() && foo < 0)) 
    error(); 

was normalerweise nicht das ist, was Sie erwarten.

0

Das erste Beispiel funktioniert, aber wenn jemand versucht, <-<= oder >= zu ändern, wird es explodieren: für bar 0 Rückkehr, wird es den ersten Teil der Aussage und testet und es wird falsch betrachten, die zweiten Abbruch check, das sollte stimmen.

Auch Ihr erstes Beispiel nicht tut, was es tun soll: Operator Vorrang von = weniger als &&, so dass Sie Zuordnung des Ergebnisses der & & -Betrieb zu foo

So bekomme ich die lieber zweites Beispiel.

0

In den meisten Situationen sollte das keine Rolle spielen. Ihr erster Fall hat einige Redundanz, daher würde ich den zweiten Vorschlag für die Kürze bevorzugen.

Es gibt einige Situationen, in denen dieser Ansatz nicht gut genug ist, insbesondere in einer Multithread-Umgebung, in der Ihre Variable ein gemeinsames Asset ist (set & Testbetrieb ist dort sehr üblich). In diesem Fall muss der Zugriff auf die Variable ordnungsgemäß geschützt werden (d. H. Durch Sperren), um eine Beschädigung von Rennen und Daten zu vermeiden.

0

Die meisten Compiler, wenn nicht alle, geben eine Warnung aus, wenn Sie versuchen, eine Zuweisung innerhalb einer bedingten zusätzlichen Klammer vorzunehmen. In den meisten Fällen würde ich argumentieren, dass es für Compound-Statements weniger lesbar ist, während es in Ruby Sinn macht, es ist einfach nicht üblich in C. Ohne eine Begründung, die Code Review IMO nie passieren würde.

Verwandte Themen