2015-09-02 21 views
8

avere il codice seguente:valori senza segno C

#include <stdio.h> 

int main() { 
    unsigned int a = -1; 
    int b = -1; 
    printf("%x\n", a); 
    printf("%x\n", b); 

    printf("%d\n", a); 
    printf("%d\n", b); 

    printf("%u\n", a); 
    printf("%u\n", b); 
    return 0; 
} 

Il risultato è:

ffffffff 
ffffffff 
-1 
-1 
4294967295 
4294967295 

posso vedere che un valore viene interpretato come con o senza segno secondo il valore trasmesso a printf funzione. In entrambi i casi, i byte sono uguali (ffffffff). Quindi, a cosa serve la parola unsigned?

+0

See: [** complemento a due - Wikipedia, l'enciclopedia libera **] (https://en.wikipedia.org/wiki/Two%27s_complement) La risposta breve è "se il bit più significativo è '1', è interpretato come un ** negativo ** intero". –

+0

http://www.cplusplus.com/forum/beginner/94567/ –

+0

Sì, ma ciò è fatto dalla funzione 'printf', quindi, non riesco a capire quale ruolo interpreti la parola' unsigned'. Nel mio esempio, per entrambi i vars firmati e non firmati ho potuto vedere il suo valore come firmato o non firmato. Per chiarire, se posso vedere una varata firmata stampata come firmata o non firmata, a cosa serve la parola 'unsigned'? – rvillablanca

risposta

5

Assegnare un int -1 a un unsigned: Come -1 non rientra in il range [0...UINT_MAX], multipli di UINT_MAX+1 vengono aggiunti fino a quando la risposta è nell'intervallo.Evidentemente UINT_MAX è pow(2,32)-1 or 429496725 sulla macchina dell'OP, quindi a ha il valore di .

unsigned int a = -1; 

Il "%x", "%u" specificatore aspetta una corrispondenza unsigned. Poiché questi non corrispondono, "Se una specifica di conversione non è valida, il comportamento non è definito. Se un argomento non è il tipo corretto per la specifica di conversione corrispondente, il comportamento non è definito." C11 §7.21.6.1 9. Lo specificatore printf non cambia b.

printf("%x\n", b); // UB 
    printf("%u\n", b); // UB 

Il "%d" specificatore aspetta una corrispondenza int. Poiché questi non corrispondono, più UB.

printf("%d\n", a); // UB 

Dato un comportamento indefinito, le conclusioni non sono supportate.


entrambi i casi, i byte sono uguali (ffffffff).

Anche con lo stesso schema di bit, tipi diversi possono avere valori diversi. ffffffff come unsigned ha il valore di 4294967295. Come int, in base alla codifica dei numeri interi con segno, ha il valore di -1, -2147483647 o TBD. Come float potrebbe essere un NAN.

cosa è la parola senza segno?

unsigned memorizza un numero intero nell'intervallo [0 ... UINT_MAX]. Non ha mai un valore negativo. Se il codice richiede un numero non negativo, utilizzare unsigned. Se il codice richiede un numero di conteggio che può essere +, - o 0, utilizzare int.


Update: per evitare un compilatore avvertimento circa l'assegnazione di un firmato int a unsigned, utilizzare il seguente. Questo è un unsigned1u negato - che è ben definito come sopra. L'effetto è lo stesso di -1, ma trasmette le intenzioni dirette del compilatore.

unsigned int a = -1u; 
+0

La tua affermazione su UB non è corretta. Per favore rileggi i paragrafi precedenti a quello che hai citato. TL; DR: qualsiasi identificatore di conversione che segue la grammatica è "valido". In altre parole in 'printf ("% d "," foo ")' l'identificatore "% d" è valido, nel senso indicato dal paragrafo citato. Certo, provare a stampare una stringa come int è UB, ma non a causa del motivo per cui sembri pensare. Piuttosto "viene eseguita la promozione del tipo corretto o la conversione, se consentito" e dal momento che nessun tipo di promozione o conversione è consentita da stringa a int, diventa UB. – AnorZaken

+0

@AnorZaken Risposta modificata per sottolineare che l'identificatore di printf e il tipo di argomento non corrispondono. – chux

-5

Nel esadecimale non è possibile ottenere un valore negativo. Quindi lo mostra come ffffffff.

Il vantaggio di utilizzare la versione senza segno (quando si sa che i valori contenuti saranno non negativo) è che a volte il computer sarà posto gli errori per voi (il programma "incidente" quando un valore negativo è assegnato alla variabile).

+2

L'assegnazione di un valore negativo a una variabile 'unsigned' ha un comportamento ben definito. –

+1

'unsigned i = -1;' restituisce sempre il valore INT_MAX assegnato a i. No crashing here –

0

Avere unsigned nella dichiarazione delle variabili è più utile per i programmatori stessi - non considerare le variabili come negative. Come hai notato, sia -1 e 4294967295 hanno la stessa rappresentazione di bit per un intero di 4 byte. È tutto su come si desidera trattare o vedere loro.

La dichiarazione unsigned int a = -1; sta convertendo -1 in complemento a due e assegnando la rappresentazione di bit in a. Lo specificatore , d e u mostrano come la rappresentazione di bit memorizzata nella variabile a si presenta in un formato diverso.

0

Quando si inizializza unsigned int a to -1; significa che si sta archiviando il complemento 2's di -1 nella memoria di a.
Che non è altro che 0xffffffff o 4294967295.

Quindi quando si stampa usando lo specificatore di formato %x or %u si ottiene quell'output.

Specificando la firma di una variabile per decidere il limite minimo e massimo di valore che può essere memorizzato.

Come con unsigned int: la gamma da 0 to 4,294,967,295 e int: l'intervallo è compreso tra -2,147,483,648 to 2,147,483,647

Per maggiori informazioni su signedness riferimento this

Problemi correlati