Frage

Macht der ANSI -Standard Mandat Die logischen Operatoren sind in C oder C ++ kurzübertragbar zu sein?

Ich bin verwirrt, denn ich erinnere mich an das K & R -Buch, dass Ihr Code nicht davon abhängen sollte, dass diese Operationen kurz geschlossen werden, denn sie können nicht. Könnte jemand bitte darauf hinweisen, wo im Standard, dass Logic Ops immer kurzbeugend ist? Ich interessiere mich hauptsächlich für C ++, eine Antwort auch für C wäre großartig.

Ich erinnere mich auch daran, dass die Bewertungsreihenfolge nicht streng definiert ist (ich kann mich nicht erinnern), daher sollte Ihr Code nicht abhängen oder annehmen, dass Funktionen innerhalb eines Ausdrucks in einer bestimmten Reihenfolge ausgeführt werden: Am Ende einer Anweisung alle referenzierten Funktionen wird aufgerufen, aber der Compiler hat die Freiheit bei der Auswahl der effizientesten Ordnung.

Zeigt der Standard die Bewertungsreihenfolge dieses Ausdrucks an?

if( functionA() && functionB() && functionC() ) cout<<"Hello world";
War es hilfreich?

Lösung

Ja, für die Betreiber sind Kurzschluss- und Bewertungsaufträge erforderlich || und && Sowohl in C- als auch in C ++ - Standards.

C ++ Standard sagt (es sollte eine äquivalente Klausel im C -Standard geben):

1.9.18

Bei der Bewertung der folgenden Ausdrücke

a && b
a || b
a ? b : c
a , b

Verwenden der integrierten Bedeutung der Bediener in diesen Ausdrücken, Nach der Bewertung des ersten Ausdrucks gibt es einen Sequenzpunkt (12).

In C ++ gibt es eine zusätzliche Falle: Kurzschluss macht es NICHT Bewerben Sie sich für Typen, die Operatoren überlasten || und &&.

Fußnote 12: Die in diesem Absatz angegebenen Operatoren sind die integrierten Operatoren, wie in Abschnitt 5 beschrieben. Wenn einer dieser Operatoren in einem gültigen Kontext überlastet ist Ein Funktionslaufung und die Operanden bilden eine Argumentliste, ohne einen implizite Sequenzpunkt zwischen ihnen.

Es wird normalerweise nicht empfohlen, diese Betreiber in C ++ zu überladen, es sei denn, Sie haben eine sehr spezifische Anforderung. Sie können es tun, aber es kann das erwartete Verhalten im Code anderer Personen brechen, insbesondere wenn diese Operatoren indirekt verwendet werden, indem Vorlagen mit dem Typ überlasteten, der diese Operatoren überlastet.

Andere Tipps

Die Bewertung der Kurzschließung und die Auswertung der Auswertung ist ein vorgeschriebener semantischer Standard sowohl in C als auch in C ++.

Wenn dies wäre, wäre Code wie dieser keine gemeinsame Redewendung

   char* pChar = 0;
   // some actions which may or may not set pChar to something
   if ((pChar != 0) && (*pChar != '\0')) {
      // do something useful

   }

Abschnitt 6.5.13 Logisch und Operator der C99 -Spezifikation (PDF -Link) sagt

(4). Im Gegensatz zum Bitwise Binary & Operator garantiert der && Operator die Bewertung von links nach rechts. Nach der Bewertung des ersten Operanden gibt es einen Sequenzpunkt. Wenn der erste Operand gleich 0 vergleicht, wird der zweite Operand nicht bewertet.

Ebenso Abschnitt 6.5.14 Logisch oder Operator sagt

(4) Im Gegensatz zum Bitgewise | Operator, der || Der Betreiber garantiert von links nach rechts eine Bewertung. Nach der Bewertung des ersten Operanden gibt es einen Sequenzpunkt. Wenn der erste Operand ungleich mit 0 vergleicht, wird der zweite Operand nicht bewertet.

Ähnliche Formulierung finden Sie in den C ++ - Standards, Überprüfen Sie den Abschnitt 5.14 in diesem Entwurfskopie. Wie Checkers in einer anderen Antwort feststellt, müssen beide Operanden bewertet werden, wenn Sie überschreiben && oder ||, da dies zu einem regulären Funktionsaufruf wird.

Ja, es schreibt dies vor (sowohl Bewertungsreihenfolge als auch Kurzschluss). In Ihrem Beispiel, wenn alle Funktionen true zurückgeben, stammt die Reihenfolge der Aufrufe streng von der Funktiona, der FunktionB und der FunktionC. Dafür verwendet wie wie

if(ptr && ptr->value) { 
    ...
}

Gleiches gilt für den Komma -Betreiber:

// calls a, then b and evaluates to the value returned by b
// which is used to initialize c
int c = (a(), b()); 

Einer sagt zwischen dem linken und dem rechten Operanden von &&, ||, , und zwischen dem ersten und zweiten/dritten Operanden von ?: (bedingter Operator) ist ein "Sequenzpunkt". Alle Nebenwirkungen werden vor diesem Punkt vollständig bewertet. Das ist also sicher:

int a = 0;
int b = (a++, a); // b initialized with 1, and a is 1

Beachten Sie, dass der Komma -Betreiber nicht mit dem syntaktischen Komma verwechselt werden soll, mit dem Dinge trennen:

// order of calls to a and b is unspecified!
function(a(), b());

Der C ++ - Standard sagt in 5.14/1:

Die && Operator gruppiert links nach rechts. Die Operanden werden beide implizit in Typ -Bool konvertiert (Klausel 4). Das Ergebnis ist wahr, wenn beide Operanden ansonsten wahr und falsch sind. Im Gegensatz zu && garantiert die Bewertung von links nach rechts: Der zweite Operand wird nicht bewertet, wenn der erste Operand falsch ist.

Und in 5.15/1:

Das || Operatorgruppen links nach rechts. Die Operanden werden beide implizit in BOOL konvertiert (Klausel 4). Es gibt wahr zurück, wenn einer seiner Operanden wahr ist, und ansonsten falsch. Im Gegensatz zu |, || garantiert von links nach rechts eine Bewertung; Darüber hinaus wird der zweite Operand nicht bewertet, wenn der erste Operand true bewertet wird.

Es heißt beide neben denen:

Das Ergebnis ist ein Bool. Alle Nebenwirkungen des ersten Ausdrucks mit Ausnahme der Zerstörung von Zeiträumen (12.2) treten vor der Bewertung des zweiten Ausdrucks auf.

Darüber hinaus, 1.9/18 sagt

Bei der Bewertung der einzelnen Ausdrücke

  • a && b
  • a || b
  • a ? b : C
  • a , b

Unter Verwendung der integrierten Bedeutung der Operatoren in diesen Ausdrücken (5.14, 5.15, 5.16, 5.18) gibt es nach der Bewertung des ersten Ausdrucks einen Sequenzpunkt.

Direkt aus dem guten alten K & R:

C garantiert das && und || werden von links nach rechts bewertet - wir werden bald Fälle sehen, in denen dies wichtig ist.

Sei sehr sehr vorsichtig.

Für grundlegende Typen sind diese Verknüpfungsbetreiber.

Wenn Sie diese Operatoren jedoch für Ihre eigene Klasse oder Aufzählungstypen definieren, sind sie keine Verknüpfung. Aufgrund dieses semantischen Unterschieds in ihrer Verwendung unter diesen unterschiedlichen Umständen wird empfohlen, diese Betreiber nicht zu definieren.

Für die operator && und operator || Für grundlegende Typen ist die Bewertungsreihenfolge nach rechts (ansonsten wäre das kurze Schneiden schwierig :-) Aber für überladene Operatoren, die Sie definieren, sind diese im Grunde genommen syntaktischer Zucker für die Definition einer Methode und somit die Reihenfolge der Bewertung der Parameter nicht definiert.

Wenn Sie Wikipedia vertrauen:

[&& und ||] unterscheiden sich semantisch von den bit-weisen Operatoren & und | Weil sie den rechten Operanden niemals bewerten werden, wenn das Ergebnis von links in Ruhe ermittelt werden kann

http://en.wikipedia.org/wiki/c_(programming_glanguage)#characteristics

Ihre Frage kommt auf C ++ - Operator Vorrang und Assoziativität. Grundsätzlich konstruiert der Compiler in Ausdrücken mit mehreren Operatoren und ohne Klammern den Expressionstaum, indem er diese Regeln befolgt.

Für Vorrang, wenn Sie so etwas haben wie A op1 B op2 C, Sie könnten Dinge als beide gruppieren (A op1 B) op2 C oder A op1 (B op2 C). Wenn op1 hat höhere Vorrang als op2, Sie erhalten den ersten Ausdruck. Ansonsten bekommen Sie den zweiten.

Für die Assoziativität, wenn Sie so etwas haben wie A op B op C, Sie könnten noch einmal Dünte gruppieren als (A op B) op C oder A op (B op C). Wenn op Hat die Assoziativität verlassen, wir haben den ersten Ausdruck. Wenn es die richtige Assoziativität hat, haben wir den zweiten. Dies funktioniert auch für Operatoren auf der gleichen Vorrangstufe.

In diesem speziellen Fall, && hat höhere Vorrang als ||, so wird der Ausdruck als bewertet als (a != "" && it == seqMap.end()) || isEven.

Die Reihenfolge selbst ist "von links nach rechts" in der Expressionsbaumform. Also werden wir zuerst bewerten a != "" && it == seqMap.end(). Wenn es wahr ist, ist der ganze Ausdruck wahr, sonst gehen wir zu isEven. Die Prozedur wiederholt sich natürlich rekursiv in der linken Unterseite.


Interessante Leckerbissen, aber das Konzept der Vorrang hat seine Wurzeln in der mathematischen Notation. Das gleiche passiert in a*b + c, wo * hat höhere Vorrang als +.

Noch interessanter/obskurer, für einen praktischen Ausdruck A1 op1 A2 op2 ... opn-1 An, wo alle Operatoren die gleiche Vorrang Katalanische Zahlen. Für große n, Diese wachsen extrem schnell. d

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top