2015-10-21 21 views
6

Per esempio, dopo aver utilizzatoUso incremento operatore ternario in C

int a = 5, b = 6; 
x = (a < b) ? a++ : b++; 

x ottiene il valore di a, che è 5, e un incremento a 6, che è previsto.

Quando uso

a = (a < b) ? a++ : b++; 

Dopo questa linea, un fermo rimane 5.

Ma

a = (a++ < b++) ? a : b; 

a è ora 6.

Perché sta succedendo e perché non è l'operatore di incremento eseguito nel primo caso?

EDIT: Giusto per chiarire, sto chiedendo perché questo accade quando sto usando queste linee separatamente, una per una, non tutte e tre nello stesso tempo.

+5

Perché dovresti ** ** voler fare qualcosa del genere? –

+3

Con gcc 4.9.3: 'a = (a chux

+2

rilevanti: http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points –

risposta

2

Entrambi i casi implicano un comportamento non definito di qualche tipo perché si sta incrementando a, restituendo a e assegnando a a sul lato sinistro all'interno di 2 punti di sequenza. 3 sarebbe richiesto per un risultato chiaramente definito.

In questo caso: a = (a < b) ? a++ : b++;

  1. se a è minore b
  2. a viene restituito (valore = 5) come risultato dell'operatore ternario
  3. a viene incrementato (valore = 6).
  4. il risultato dell'operatore ternario (5) è assegnato al lato sinistro variabile a (over-crei 6)

L'ordine delle fasi 3 e 4 non è definito.È equivalente a a = a++;

In questo caso: a = (a++ < b++) ? a : b;

  1. Se a è minore che b
  2. a e b vengono incrementati (indipendentemente che è più piccolo)
  3. a viene restituito come risultato dell'operatore ternario
  4. è assegnato alla variabilelato sinistro

L'ordine dei passaggi 2 e 3 non è chiaramente definito.

È importante tenere traccia dei punti di sequenza in questi casi. Regole rilevanti:

  • La prima espressione dell'operatore ternario a sinistra di ? viene sequenziata prima della seconda o della terza espressione. E uno di questi viene sequenziato prima dell'assegnazione.
  • Il confronto viene sequenziato prima della ?
  • Nelle espressioni come a++ il valore viene restituito prima incrementare

comportamento indefinito:

  • Nelle espressioni come a = a++; v'è alcun punto sequenza tra (posta) incrementando a e assegnando a a sul lato sinistro. Entrambi si verificano dopo che è stato restituito il valore originale di
  • In espressioni come a++ ? a : b non esiste un punto di sequenza tra (post) incrementale a e il ritorno a dall'operatore ternario. Sia accadere dopo la ?
+0

Perché sarebbe l'incremento e l'assegnazione essere eseguito in ordine diverso per i due casi? –

+1

Nel primo caso, rimane 5, non incrementa a 6. – Pyranth

4
a = (a < b) ? a++ : b++; 

qui, abbiamo memorizzato un in una, e poi incrementato esso. Ma è come

a = a++; // as a<b 

che mostra un comportamento non definito.

a = (a++ < b++) ? a : b; 

qui, una viene incrementato al momento del confronto, così ora a è 6, che è memorizzato in una.

+0

perché? Si può descrivere per favore? @haccks – Mukit09

1

Quella linea che ti dà il risultato inatteso è un errore: non si permettono di modificare un oggetto (qui a) due volte nella stessa espressione senza separarli da un "punto di sequenza" .

Il ? nell'altro è un punto di sequenza, in modo che uno funziona.

Se si esegue questa operazione (modifica due volte senza punto di sequenza), il comportamento del programma diventa indefinito. Cioè non è possibile fare una ragionevole supposizione di ciò che il programma dovrebbe produrre e quindi si vedono dei risultati inattesi che possono variare a seconda del compilatore e della sua versione.

0

Dal horse's mouth:

6.5 Expressions
...
2 If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings. 84)
84) This paragraph renders undefined statement expressions such as
i = ++i + 1; 
    a[i++] = i;
while allowing
i = i + 1; 
    a[i] = i;
6.5.15 Conditional operator
...
4 The first operand is evaluated; there is a sequence point between its evaluation and the evaluation of the second or third operand (whichever is evaluated). The second operand is evaluated only if the first compares unequal to 0; the third operand is evaluated only if the first compares equal to 0; the result is the value of the second or third operand (whichever is evaluated), converted to the type described below. 110)
110) A conditional expression does not yield an lvalue.
6.5.16 Assignment operators
...
3 An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, 111) but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion. The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.
111) The implementation is permitted to read the object to determine the value but is not required to, even when the object has volatile-qualified type.

Nell'espressione

a = (a < b) ? a++ : b++ 

c'è un punto di sequenza tra la valutazione di (a < b) e a++, ma non v'è alcun punto sequenza tra la valutazione di a su il LHS dell'operatore = e a++; quindi, il comportamento non è definito.

Nell'espressione

a = (a++ < b++) ? a : b 

c'è un punto sequenza tra (a++ < b++) e a sul RHS dell'operatore ?, ma è inutile sequenza tra il a sul lato sinistro della = dell'operatore e (a++ < b++); di nuovo, il comportamento non è definito.