2010-02-14 11 views
5

I disallineamenti firmati/non firmati sono necessariamente negativi?C89: disaccordo firmato/non firmato

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?

+0

Non proprio un dupe, ma vale la pena leggerlo comunque: http://stackoverflow.com/questions/859943/c-how-can-i-fix-warnings-like-comparison-between-signed-and-unsigned – finnw

risposta

9

"disallineamenti firmati/non firmati" possono essere errati. 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 unsigned. Così,

int i = -1; 
unsigned int j = 10; 

if (i < j) 
    printf("1\n"); 
else 
    printf("2\n"); 

stampe 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 quindi risulta falsa e si arriva alla clausola else.

Per il tuo esempio particolare, argc è garantito non negativo, quindi non devi preoccuparti della "mancata corrispondenza".

+0

why firmato convertito in unsigned (perché non viceversa)? questo comportamento è standardizzato? – triclosan

+0

@triclosan, sì. Le regole sono leggermente complesse, ma per 'int' e' unsigned int', poiché hanno lo stesso rank, il tipo firmato viene convertito nel tipo unsigned. Vedi la sezione 6.3.1.8 di N1256 per i dettagli. –

1

Non è un problema reale nel tuo caso particolare, ma il compilatore non può sapere che argc avrà sempre valori che non causeranno alcun problema.

+0

Se 'argc' è troppo grande per rientrare in un' int', hai comunque seri problemi :-) – finnw

+0

Non necessariamente. 'INT_MAX' può essere basso come 32767 e ho visto linee di comando che superano diverse centinaia di kilobyte. È noto che l'utility xargs (1) raggiunge facilmente quel limite. – Jens

1

È solo indirettamente un problema.

cose brutte possono accadere se si utilizzano interi firmati per operazioni bit per bit, come &, |, << e >>.
completamente diverse cose brutte possono accadere se si utilizzano numeri interi senza segno per l'aritmetica (underflow, cicli infiniti quando si verifica se un numero è >= 0 etc.)

A causa di questo, alcuni compilatori e strumenti di verifica statica emetterà avvisi quando si mescolano interi con segno e senza segno in entrambi i tipi di operazione (aritmetica o manipolazione dei bit.)

Sebbene sia possibile mischiarli in casi semplici come nell'esempio, se lo si fa significa che non è possibile utilizzare quegli strumenti di controllo statici (o deve disabilitare quegli avvertimenti) il che potrebbe significare che altri bug non vengono rilevati.

A volte non hai scelta, ad es. quando si esegue l'aritmetica su valori di tipo size_t nel codice di gestione della memoria.

Nel tuo esempio vorrei bastone a int, proprio perché è più semplice avere un minor numero di tipi, e il int sta per essere lì in ogni caso in quanto è il tipo del primo argomento a main().

1

Non male. Correggerei gli avvisi del compilatore relativi alla mancata corrispondenza firmata/non firmata perché possono accadere cose brutte anche se improbabili o impossibili. Quando si deve correggere un bug a causa della mancata corrispondenza firmata/non firmata, il compilatore sta fondamentalmente dicendo "Te l'avevo detto". Non ignorare l'avviso è lì per un motivo.

Problemi correlati