2015-04-22 5 views
9

Quando compilo il seguente codice con GCC:-Wconversion improvviso durante l'uso dell'operatore << = on unsigned char

int main() 
{ 
    unsigned char c = 1; 
    c <<= 1; // WARNING ON THIS LINE 
    return 0; 
} 

ottengo questo avvertimento:

conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion]

Perché ? Cosa c'è di sbagliato con questo codice? In realtà, posso davvero usare l'oprator <<= su una variabile unsigned char? Comando

Compilation:

g++ test.cpp -Wconversion -o test.exe

+1

Questa, mi sembra, è una di quelle situazioni "dannate se si fa e dannazione se non si", sia per i compilatori che per gli utenti. Come utente, ciò che hai scritto è pulito e produce la risposta desiderata ed è generalmente del tutto ineccepibile. E non ha bisogno di ulteriore confusione linguistica per renderlo più difficile da capire. Come scrittore di compilatori, c'è tecnicamente una conversione restringente, quindi l'avvertimento è tecnicamente corretto. Ma non posso fare a meno di pensare che in questo contesto, o quelli analoghi che implicano 'short' (che presumibilmente attivano anche l'avvertimento), l'avvertimento non è davvero costruttivo. –

risposta

8

Questo è un avvertimento valida:

c <<= 1; 

è equivalente a:

c = c << 1 

e le regole per << affermano che gli operandi vengono promossi e in tal caso verranno promossi a int e il risultato è del tipo promosso. Quindi ci sarà una conversione da int a unsigned char alla fine che potrebbe risultare in un valore alterato.

Il codice è valido, l'avviso indica che è in corso una conversione implicita e in alcuni casi la conversione potrebbe alterare il valore. L'uso di un cast silenzia l'avviso. I risultati delle conversioni implicite possono essere molto contro-intuitivi e in alcuni casi un comportamento indefinito. Vedi lo gcc Wconversion wiki for some details.

Non vedo un modo per rimuovere l'avviso senza espandere l'operazione manualmente e con static_cast:

c = static_cast<unsigned char>(c << 1); 

Come si può vedere dalla lunga discussione su questo gcc bug report non tutti si sentono che questo è un caso utile per questo avviso.

di rinvio del draft C++ standard sezione 5.8 operatori di spostamento:

Gli operandi sono di tipo censimento integrale o senza ambito e promozioni integrali vengono eseguite. Il tipo del risultato è quello dell'operando sinistro promosso [...]

e dalla sezione 5.17 assegnazione e assegnazione composti operatori:

il comportamento di un'espressione della forma op E1 = E2 è equivalente a E1 = E1 op E2 tranne che E1 è valutato una sola volta. [...]

+1

Ho anche il problema se un do 'c << = static_cast (1);'. Stai dicendo che non esiste un operatore di spostamento per i tipi di 1 byte in C++? : -/ – Caduchon

+4

Vedere [Perché un breve essere convertito in un int prima delle operazioni aritmetiche in C e C++?] (Http://stackoverflow.com/q/24371868/1708801) per una spiegazione del motivo per cui gli operandi vengono promossi a tipi più ampi . Principalmente perché si traduce in un codice generato più veloce. –