Il ciclo contiene un comportamento non definito a causa dell'intero underflow?
Innanzitutto questa è una Boolean Conversion:
Un prvalue di integrale, virgola mobile, l'enumerazione senza ambito, puntatore, e tipi puntatore-a-membro può essere convertito in un prvalue di tipo bool
.
Il valore zero (per l'enumerazione integrale, a virgola mobile e senza ambito) e il puntatore nullo ei valori da puntatore a membro nullo diventano false
. Tutti gli altri valori diventano true
.
Quindi non ci sarà alcun integer underflow se i
sia correttamente inizializzato, raggiungerà 0U
e che sarà lanciato ad un valore false
.
Così che cosa il compilatore sta facendo in modo efficace ecco: while(static_cast<bool>(i--))
Non compilatori hanno diritto di presumere che, mentre condizione del ciclo è sempre true
a causa di questo e finire con ciclo infinito?
Il motivo chiave per cui questo non è un ciclo infinito è che il valore postfix decrement operator restituisce il valore della variabile decrementata. È definito come T operator--(T&, int)
E come discusso in precedenza, il compilatore sta valutando se tale valore è 0U
come parte della conversione in bool
.
Quello che il compilatore è effettivamente facendo qui è: while(0 != operator--(i, 1))
Nel vostro aggiornamento di citare questo codice come una motivazione per la tua domanda: comportamento
void fn(void)
{
/* write something after this comment so that the program output is 10 */
int a[1] = {0};
int j = 0;
while(a[j] != 5) ++j; /* Search stack until you find 5 */
a[j] = 10; /* Overwrite it with 10 */
/* write something before this comment */
}
A un esame, che l'intero programma è undefined c'è solo 1 elemento di a
ed è inizializzato a 0. Pertanto, per qualsiasi indice diverso da 0
, a[j]
sta guardando alla fine dell'array. Continuerà fino a quando non viene trovato un 5
o fino a quando il sistema operativo non funziona perché il programma ha letto dalla memoria protetta. Questo è diverso dalla condizione del loop che uscirà quando l'operatore di decremento postfix restituirà un valore pari a 0, quindi non è possibile supporre che questo sia sempre true
o che il ciclo continui all'infinito.
Cosa succede se i
è signed int
?
Entrambe le conversioni di cui sopra sono incorporate in C++. E sono entrambi definiti per tutti i tipi interi, firmati e non firmati. Quindi in definitiva questo si espande a:
while(static_cast<bool>(operator--(i, 1)))
Non contiene insidie relative all'accesso agli array?
Anche in questo caso sta chiamando un operatore di built-in, la subscript operator: T& operator[](T*, std::ptrdiff_t)
Così a[i]
è l'equivalente di chiamare operator(a, static_cast<ptrdiff_t>(i))
Quindi la domanda ovvia follow è ciò che è un ptrdiff_t
? È un intero definito dall'implementazione, ma in quanto tale ogni implementazione dello standard è responsabile della definizione delle conversioni da e verso questo tipo, pertanto i
verrà eseguito correttamente.
Bene, questo è ** non ** un ciclo infinito. –
Cosa è successo quando lo hai eseguito? –
Nessun problema, dal momento che 'while (0)' è falso e non ti interessa il valore di 'i' dopo – MrTux