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.