Quando abbiamo l'espressione E1 ? E2 : E3
, sono coinvolti quattro tipi. Le espressioni E1
, E2
e E3
hanno ciascuna un tipo (ei tipi di E2
e E3
possono essere diversi). Inoltre, l'intera espressione E1 ? E2 : E3
ha un tipo.
Se E2
e E3
hanno lo stesso tipo, allora questo è semplice: l'espressione generale ha quel tipo. Siamo in grado di esprimere questo in una meta-notazione in questo modo:
(T1 ? T2 : T2) -> T2
"The type of a ternary expression whose alterantives are both of the same type T2
is just T2."
Se non hanno lo stesso tipo, le cose si fanno un po 'interessante, e la situazione è molto simile a E2
e E3
essere coinvolti insieme in un aritmetica operazione. Ad esempio, se si aggiunge unoe float
, l'operando int
viene convertito in float
. Questo è ciò che sta accadendo nel tuo programma. La situazione tipo è:
(int ? float : int) -> float
il test fallisce, e quindi il valore 0
int
viene convertito nel valore 0.0
float
.
Questo valore float
non è compatibile con lo specificatore %d
conversione di printf
, che richiede un int
.
Più precisamente, il valore float
subisce un altro. Quando un float
viene passato come uno degli argomenti trascinamento a una funzione variadic, viene convertito in double
.
Quindi il valore double
0.0 viene passato a printf
dove si aspetta int
.
In ogni caso, è un comportamento non definito: è un codice non portatile per il quale la definizione standard ISO del linguaggio C non offre un significato.
Da qui in poi, possiamo applicare un ragionamento specifico della piattaforma perché non vediamo semplicemente 0
. Supponiamo che int
sia un tipo a 32 bit e quattro byte e che double
sia la rappresentazione comune a 64 bit, 8 byte, IEE754 e che venga utilizzato un valore a zero bit per 0.0
. Quindi, perché non una parte a 32 bit di questo all-bit-zero viene trattata da printf
come valore 0
?
È possibile che il valore dell'argomento double
a 64 bit imponga l'allineamento di 8 byte quando viene inserito nello stack, eventualmente spostando il puntatore dello stack di quattro byte. E quindi printf
estrae i dati obsoleti da questi quattro byte anziché i bit zero dal valore double
.
Che cosa intendi esattamente per "casuale"? Stai cercando di stampare un numero in virgola mobile come numero intero, ma quel numero dovrebbe essere '0' che ha la stessa rappresentazione di bit in entrambi i tipi. –
Casuale o solo errato? –
Questa domanda sembra essere fuori tema perché riguarda chi sa cosa. –