2013-03-21 13 views
5

Sto avendo difficoltà a comprendere il motivo per cui il seguente codice non avvisa:La mancanza di avvertimenti sul contatore del ciclo

unsigned test = 0xffffffff; 

for (unsigned char i = 0; i < test; i++) 
{ 
    // Some code 
} 

Questo è il Visual Studio 2010, ma a quanto pare GCC non avvisa neanche. Qualcuno sa perché?

+0

Mostra le bandiere di costruzione, quali avvisi stai richiedendo? – unwind

+1

Perché l'avviso non è un comportamento predefinito, quindi è necessario creare un caso * per * avviso? – Jon

+0

fw, c'è un avvertimento se si contrassegna 'test' come' const'. – mitchnull

risposta

6

Da un punto di vista linguistico, non c'è nulla da mettere in guardia. i viene promosso a unsigned int prima che venga valutato lo <. Ed è perfettamente ben definito per incrementare uno unsigned char in modo tale da portarlo a zero.

Il fatto che questo codice faccia qualcosa di irritante è sfortunato. Ma non è chiaro quale regola debba essere applicato da un compilatore per rilevare questo tipo di cose.

Grazie alla @unwind nei commenti qui sotto: è possibile ottenere GCC per mettere in guardia circa il fatto che questo confronto deve essere sempre valutata come vera utilizzando il flag -Wtype-limits.

Aggiornamento 2: A quanto pare l'opzione di cui sopra non funziona in questo caso (non ho una versione "moderna" di GCC a portata di mano in questo momento ...)

+0

Ah .. ovviamente! Grazie. –

+1

GCC ha un avvertimento (['-Wtype-limits'] (http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wtype_002dlimits-411)) che mette in guardia per confronti sempre fedeli, Immagino che si applicherebbe qui. – unwind

+0

@unwind: Questo è un buon punto; il vero problema è che il confronto deve sempre valutare il vero. –

1

i è promosso a unsigned e quindi confrontato con test. Nessun problema qui. Bene. i ++ traboccherà il char, ma questo è un problema in fase di esecuzione. Quello che intendo è che dopo 255 sarà 0, e che forse non è ciò che l'autore vede, rendendo il ciclo potencialy infinito se non c'è altra forma di terminarlo (una rottura, un retun, ecc.) Che è un possibile "logico" "Errore di run time.

+0

* "i ++ traboccherà il char, ma si tratta di un problema in fase di esecuzione." * - "i' does * never * overflow, quindi non c'è nessun problema di run-time. –

+0

@Christian Rau Ovviamente, quello che intendo è che dopo 255 sarà 0, e che forse non è ciò che l'autore vede, rendendo il ciclo potencialy infinito se non ce n'è altro per terminarlo (una pausa, un retun, ecc.) Questo è un errore "run time" logico possibile. – qPCR4vir

1

Perché confrontare uno unsigned char e unsigned è perfettamente legale. Il problema inizia solo a manifestarsi a causa del loop count che evidentemente trabocca, ma non sono sicuro che i compilatori saranno mai that smart.

+0

* "Il problema inizia a manifestarsi solo a causa del contatore di loop evidentemente eccessivo, ma non sono sicuro che i compilatori siano così intelligenti." * - Anche il compilatore non deve essere così intelligente, perché questo non è nemmeno un problema , poiché i tipi non firmati non possono mai traboccare. –

+1

Bene, il contatore dei cicli si avvolge solo dopo 255, creando effettivamente un ciclo infinito. Questo è quello che intendevo ... Penso che la parola corretta sia * carry *. –

+0

Sì, ma questo non è un problema reale da diagnosticare, in quanto solo il programmatore può anche definire se questo dovrebbe accadere o meno. Non è che il compilatore sia troppo stupido o cattivo nell'ayayzing per trovare questo * "problema" *. Lui non dovrebbe nemmeno considerarlo. –

1

dal progetto di norma:

4.5 promozioni integrali

Una prvalue di tipo intero diverso da bool, char16_t, char32_t o wchar_t cui intero rango conversione (4.13) è inferiore che il grado di int può essere convertito in un valore di tipo int se int può rappresentare tutti i valori del tipo di sorgente ; in caso contrario, il valore di origine può essere convertito in un valore di di tipo unsigned int.

Problemi correlati