C89: mancata corrispondenza firmata/non firmata
Domanda
Sono necessari disallineamenti firmati/non firmati?
Ecco il mio programma:
int main(int argc, char *argv[]) {
unsigned int i;
for (i = 1; i < argc; i++) { // signed/unsigned mismatch here
}
}
argc
è firmato, i
non è. È un problema?
Soluzione
"I disallineamenti firmati/non firmati" possono essere cattivi. Nella tua domanda, stai chiedendo dei confronti. Quando si confrontano due valori dello stesso tipo di base, ma uno firmato e uno non firmato, il valore firmato viene convertito in non firmato. Così,
int i = -1;
unsigned int j = 10;
if (i < j)
printf("1\n");
else
printf("2\n");
Stampa 2, non 1. Questo perché in i < j
, i
viene convertito in un unsigned int
. (unsigned int)-1
è uguale a UINT_MAX
, un numero molto grande. La condizione valuta quindi false e si arriva al else
clausola.
Per il tuo esempio particolare, argc
è garantito per essere non negativo, quindi non devi preoccuparti della "mancata corrispondenza".
Altri suggerimenti
Non è un vero problema nel tuo caso particolare, ma il compilatore non può sapere che Argc avrà sempre valori che non causano problemi.
Non è male. Risolverei gli avvisi di compilatore riguardanti la mancata corrispondenza firmata/non firmata perché possono accadere cose cattive anche se sono improbabili o impossibili. Quando devi correggere un bug a causa della mancata corrispondenza firmata/non firmata, il compilatore sta fondamentalmente dicendo "te l'ho detto". Non ignorare l'avvertimento è lì per un motivo.
È solo indirettamente un problema.
Cose brutte possono accadere se usi numeri interi firmati per operazioni bitwise come &
, |
, <<
e >>
.
Possono accadere cose cattive completamente diverse se usi numeri interi non firmati per aritmetica (underflow, anelli infiniti quando si verifica se un numero lo è >= 0
eccetera.)
Per questo motivo, alcuni compilatori e strumenti di controllo statici emetteranno avvertimenti quando si mescolano numeri interi firmati e non firmati in entrambi i tipi di operazione (aritmetica o manipolazione di bit.)
Sebbene possa essere sicuro mescolarli in casi semplici come il tuo esempio, se lo fai significa che non è possibile utilizzare quegli strumenti di controllo statici (o devono disabilitare tali avvertimenti) che possono significare che altri bug non vengono rilevati.
A volte non hai scelta, ad esempio quando fai aritmetica sui valori di tipo size_t
nel codice di gestione della memoria.
Nel tuo esempio mi attenerei int
, solo perché è più semplice avere meno tipi e il int
ci sarà comunque dentro in quanto è il tipo del primo argomento main()
.