2016-02-26 8 views
17

Wenn boolean 0 ist, gibt es 9 aus, aber wenn es 1 ist, gibt es 10 aus. Ich weiß, dass dies wegen der Priorität geschieht, aber nicht genau herausfinden kann, wie es passiert. Bitte hilf mir, dies zu verstehen.Wie wird dieser ternäre Bedingungsausdruck ausgeführt?

HINWEIS: Ich weiß, dass ich die erwartete Ausgabe erhalten kann, wenn ich Klammern verwende, oder besser einen sauberen Code schreibe. Ich benutze das nur, um zu verstehen, wie der Compiler Ausdrücke wie diese nach Priorität bewertet.

+0

optimieren, es ist besser, 'true' und' false' mit boolean – Garf365

+4

zu verwenden Lesen Sie nach dem _comma operator_ and prefix Inkrementdekrement. –

+1

Und welche Ausgabe würden Sie erwarten? –

Antwort

40

, hat niedrigere Priorität als ?:. Was bedeutet, dass die volle parenthesising ist:

int k = ((boolean ? (++x, ++y) : --x), --y); 

Wie Sie sehen können, ist k immer auf den Wert von --y initialisiert. Es ist nur so, wenn booleantrue ist, passiert ++y davor.


Wenn für die volle Klammer Form eines Ausdrucks suchen, betrachten Sie es als den Ausdrucksbaum konstruieren (wo der niedrigsten Priorität Operator an der Wurzel ist).

Suchen Sie den Operator mit der niedrigsten Priorität in einem Ausdruck, und klammern Sie das Argument auf der linken Seite und das Argument auf der rechten Seite in Klammern ein. Wiederhole rekursiv innerhalb der nur in Klammern gesetzten Unterausdrücke.

+0

Vielen Dank, Ihre Antwort hat geholfen, können Sie mir die Schritte zum Klammern eines bestimmten Ausdrucks angesichts der Priorität sagen, ich bin nicht in der Lage zu entscheiden, welche Gruppen für solche Ausdrücke in Klammern gesetzt werden. –

+0

@KaranJoisher Ich habe versucht, die Antwort entsprechend zu erweitern. – Angew

+1

@KaranJoisher Warum nicht einfach die Parens einfügen, um alle Mehrdeutigkeiten zu entfernen: 'int k = (boolesch? (++ x, ++ y): (--x, --y));' Macht es sofort offensichtlich welche Teile wohin gehen. Es muss nicht versucht werden, den Vorrang der Operatoren herauszufinden. –

22

Aufgrund der Komma-Operator ist die niedrigste operator precedence, Ihre Aussage mit y tatsächlich gleich

k = (boolean ? (++x, ++y) : --x), --y; 

Das heißt, wenn boolean ist true Sie beide zu erhöhen und verringern. Das Ergebnis des ternären Ausdrucks wird in beiden Fällen verworfen, und k wird nur das Ergebnis --y zugewiesen.

Es ist zu beachten, dass dies kein undefiniertes Verhalten ist, da der Kommaoperator einen Sequenzpunkt einführt.


das Ergebnis erhalten Sie erwarten, müssen Sie

k = boolean ? (++x, ++y) : (--x, --y); 

Beachten Sie, dass die Klammern um ++x, ++y zu tun, ist streng genommen nicht erforderlich, aber es macht den Ausdruck klarer.

+3

Ich frage mich, ob jemand über die Nicht-UBness des Codes sprechen würde. Dank dafür. – NathanOliver

+1

@NathanOliver Nun, es ist * wichtig in solchen Fällen. :) –

+1

@NathanOliver Du würdest UB dafür verdienen, Code wie diesen zu schreiben. Ich bin kein Compiler, ich möchte Code nicht analysieren. – edmz

8

die oben genannten ausgezeichneten Antworten gegeben, sollte man stattdessen schreiben:

if (boolean) { 
    ++x; 
    ++y; 
} else { 
    --x; 
    --y;  
} 
int k = y; 

Denn dann der Code lesbar und klar in seiner Absicht ist. Dies wird jedem helfen, der den Code pflegen muss (einschließlich des ursprünglichen Autors!), Ohne dass jemand Zeit verschwenden muss, indem er SO Fragen stellt oder sich um den Vorrang von , oder ?: kümmert oder was die Logistik der Zuordnung zu solch einem komplexen Ausdruck ist.Jeder moderne Compiler wird sowohl diesen als auch den obigen zum selben resultierenden Code

+6

OP's Post ist clevere Verwendung von Sequenzierung, aber auch die Art von "clever", die Ihre Mitarbeiter dazu bringen wird, Sie zu hassen. – MtRoad

+1

ja, guter Punkt, endlich. –

+0

Können die Down-Wähler erklären warum? Fehle mir eine entscheidende Vor-Optimierungsmöglichkeit, die so wichtig ist, dass mein Code bedeutungslos ist? Bitte geben Sie mir einen guten Grund, eine Initialisierung als OPs zu schreiben. Oder nicht wie meins. –