Come funziona esattamente l'operatore?: In C?


10

Ho una domanda, come funziona il compilatore sul seguente codice:

#include<stdio.h>

int main(void)
{
  int b=12, c=11;
  int d = (b == c++) ? (c+1) : (c-1);
  printf("d = %i\n", d);
}

Non sono sicuro che il motivo per cui il risultato è d = 11.


1
Perché non sei sicuro? Cos'altro ti aspetteresti e perché?
Gerhardh,

2
Non ricordo l'esatta semantica implicata, ma potresti osservare un comportamento indefinito.
Chepner,

3
No, @chepner, c'è un punto sequenza dopo aver valutato la condizione di un ternario, prima di valutare l'alternativa selezionata. Ciò evita il vettore UB suppongo che tu stia pensando.
John Bollinger,

Sì, non sono sicuro di dove pensassi che il compilatore avrebbe potuto scegliere.
Chepner,

Risposte:


6

In int d = (b == c++) ? (c+1) : (c-1);:

  • Il valore di c++è il valore corrente di c, 11. Separatamente, cviene incrementato a 12.
  • b == 11è falso, poiché bè 12.
  • Poiché (b == c++)è falso, (c-1)viene utilizzato. Inoltre, l'incremento di ca 12 deve essere completato da questo punto.
  • Poiché cè 12, c-1è 11.
  • d è inizializzato su quel valore, 11.

5

Secondo lo standard C (6.5.15 Operatore condizionale)

4 Viene valutato il primo operando; esiste un punto di sequenza tra la sua valutazione e la valutazione del secondo o terzo operando (qualunque sia la valutazione). Il secondo operando viene valutato solo se il primo confronta in modo diverso da 0; il terzo operando viene valutato solo se il primo confronta uguale a 0; il risultato è il valore del secondo o terzo operando (qualunque sia valutato), convertito nel tipo descritto di seguito.110)

Quindi nell'espressione inizializzante di questa dichiarazione

int d = (b == c++) ? (c+1) : (c-1);

la variabile bviene confrontata con il valore della variabile cperché l'operatore post-incremento restituisce il valore del suo operando prima di incrementarlo.

Poiché i valori non sono uguali ( bè impostato su 12 mentre cè impostato su 11), (c-1)viene valutata la sottoespressione .

Secondo la citazione c'è un punto sequenza dopo la valutazione delle condizioni dell'operatore. Significa che dopo la valutazione della condizione cha il valore 12dopo aver applicato l'operatore post-incremento alla variabile c. Di conseguenza la variabile d è inizializzata dal valore 1( 12 - 1).


2
L'unica risposta corretta - questo caso specifico deve essere risolto citando il punto in sequenza ?:. Perché normalmente in C, la combinazione ++con altre operazioni sullo stesso operando è un comportamento indefinito. E questo codice funziona prevedibilmente solo perché ?:ha varie regole speciali per i fiocchi di neve.
Lundin,

4

Perché la condizione è falsa, quindi il falsecaso accadrà :, c-1ma poiché cla condizione è stata incrementata di c++, quindi cè ora 12. Il risultato quindi 12 - 1 che è 11.

EDIT: Ciò che OP ha frainteso era l'incremento post.

Quindi ciò che realmente accade è così:

#include<stdio.h>
int main(void)
{
  int b=12, c=11;
  int d;

  if (b == c) { // 12 == 11 ? -> false
    c = c + 1;
    d = c + 1;
  } else { // this executes since condition is false
    c = c + 1; // post increment -> c++ -> c = 12 now
    d = c - 1; // 12 - 1 = 11 -> d = 11
  }
  printf("d = %i\n", d);
}

1
Penso che l'OP si riferisca all'ordine delle operazioni, dato c++nella condizione. La condizione è falsa, ma viene quindi utilizzato il valore originale di cper calcolare c - 1, non la versione incrementata.
Chepner,

1
Ho pensato che sincero 12 == 11 + 1 sia vero ...
J0S l'

Ma questo non è vero poiché viene utilizzato il nuovo valore c o mi manca il tuo punto?
Eraklon,

Penso che potrebbe esserci un malinteso tra c++e++c
ChatterOne l'

@ N00b c++è il posto dell'operatore -increment. Il valore di c++è 11, con l'effetto collaterale di fare c == 12. ++cavrebbe il valore di 12.
chepner,

4

Tradotto in una normale istruzione if il tuo codice sarebbe simile al seguente:

int b=12, c=11;
int d;

if (b == c++)
   d = c+1;
else
   d = c-1;

L'indizio qui è che c viene incrementato dopo il controllo della condizione. Quindi si inserisce lo elsestato ma c ha già il valore 12 lì.


1

Fare riferimento a Operatore ternario.

Sintassi

condizione ? value_if_true: value_if_false

Quindi, hai scritto

int d = (b == c++) ? (c+1) : (c-1);

In questa situazione, il risultato sarà 11 perché, dopo i controlli, il valore 'c' viene aumentato (c + 1 = 12) e solo dopo imposta il valore 'd' come c (12) -1 che è 11.

Se hai usato, ad esempio:

int d = (b == ++c) ? (c+1) : (c-1);

Il valore "c" verrebbe aumentato prima di controllare l'istruzione, quindi sarebbe vero e il valore "d" sarebbe c (12) +1 che è 13.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.