2012-01-28 27 views
29

int:La vera differenza tra "int" e "unsigned int"

Il tipo di dati int a 32 bit può contenere valori interi nell'intervallo -2.147.483.648 a 2.147.483.647. È inoltre possibile fare riferimento a questo tipo di dati come firmato o firmato.

unsigned int:

Il 32-bit di dati int senza segno tipo può contenere valori interi nell'intervallo da 0 a 4.294.967.295. È possibile che si riferisca a questo tipo di dati semplicemente come non firmato.

Ok, ma, in pratica:

int x = 0xFFFFFFFF; 
unsigned int y = 0xFFFFFFFF; 
printf("%d, %d, %u, %u", x, y, x, y); 
// -1, -1, 4294967295, 4294967295 

alcuna differenza, O.Ö. Sono un po 'confuso.

+1

È necessario pensare alla rappresentazione _binary_ di entrambi un 'int' e un' unsigned int'. – Oded

+1

La vera ragione per cui questo può accadere è che C è * debole * * tipizzato * linguaggio. Ma 'unsigned int' e' int' sono molto diversi. – cha0site

+1

http://stackoverflow.com/questions/247873/signed-versus-unsigned-integers –

risposta

34

Hehe. Hai un cast implicito qui, perché stai dicendo a printf che tipo aspettarsi.

Prova questo per dimensioni invece:

unsigned int x = 0xFFFFFFFF; 
int y = 0xFFFFFFFF; 

if (x < 0) 
    printf("one\n"); 
else 
    printf("two\n"); 
if (y < 0) 
    printf("three\n"); 
else 
    printf("four\n"); 
21

Sì, perché nel tuo caso usano the same representation.

La sequenza di bit 0xFFFFFFFF accade per assomigliare -1 se interpretato come 32b firmato intero e come 4294967295 quando interpretato come un intero senza segno 32b.

È lo stesso di char c = 65. Se lo interpreti come un intero con segno, è 65. Se lo interpreti come personaggio è a.


Come R e pmg sottolineano, tecnicamente è un comportamento indefinito passare argomenti che non corrispondono agli identificatori di formato. Quindi il programma potrebbe fare qualsiasi cosa (dalla stampa di valori casuali all'arresto anomalo, alla stampa della cosa "giusta", ecc.).

punti standard fuori in 7.19.6.1-9

Se una conversione speci fi cazione non è valido, il comportamento è unde definito. Se qualsiasi argomento non è il tipo corretto per la specifica conversione , il comportamento non è definito.

+4

Il vero motivo è che sta usando% u per stampare entrambi. –

+3

La vera ragione è che lui ** ha invocato un comportamento non definito ** passando una stringa di formato di corrispondenza non di tipo a 'printf'. Voglio quasi sviare tutte le risposte che stanno saltando questo e sottolineando roba irrilevante sulla rappresentazione ... –

+1

@R .. Esatto, non corrisponde il formato e gli argomenti sono comportamenti indefiniti. Sentitevi liberi di downvotare, non mi dispiace :-) – cnicutar

1

il tipo indica solo ciò che il bit pattern deve rappresentare. i bit sono solo ciò che ne fai di loro. le stesse sequenze possono essere interpretate in modi diversi.

1

I printf funzione interpreta il valore che si passa secondo del formato, in una posizione corrispondente. Se comunichi allo printf di passare uno int, ma invece di passare unsigned, lo printf reinterpreterà uno come l'altro e stamperà i risultati visualizzati.

3

La rappresentazione interna di int e unsigned int è lo stesso.

Pertanto, quando si passa la stessa stringa di formato a printf, verrà stampato come lo stesso.

Tuttavia, ci sono differenze quando li si confronta. Considerare:

int x = 0x7FFFFFFF; 
int y = 0xFFFFFFFF; 
x < y // false 
x > y // true 
(unsigned int) x < (unsigned int y) // true 
(unsigned int) x > (unsigned int y) // false 

questo può essere anche un avvertimento, perché quando si confrontano firmato e unsigned integer uno di loro sarà implicitamente colato per abbinare i tipi.

7

Il problema è che hai invocato Undefined Behaviour.


quando si richiama UB tutto può succedere.

Gli incarichi sono ok; v'è una conversione implicita nella prima linea

int x = 0xFFFFFFFF; 
unsigned int y = 0xFFFFFFFF; 

Tuttavia, la chiamata a printf, non è ok

printf("%d, %d, %u, %u", x, y, x, y); 

È UB al disallineamento del % identificatore e il tipo dell'argomento.
Nel tuo caso si specificano 2 int s e 2 unsigned int s in questo ordine per fornire 1 int, 1 unsigned int, 1 int e 1 unsigned int.


Non fare UB!

+0

-1, sbagliato. Questo non è un comportamento indefinito. Consulta C99 sezione 6.5.2.2, paragrafo 6. – cha0site

+1

@ cha0site: ho detto esplicitamente che i compiti sono ok: * la sezione 6.5.2.2 paragrafo 6 * non si applica in realtà alla mia risposta. L'UB è nella chiamata 'printf': controlla [7.19.6.1] (http://port70.net/~nsz/c/c99/n1256.html#7.19.6):" Se qualche argomento non è il tipo corretto per la corrispondente specifica di conversione, il comportamento non è definito ". Notare anche che 'printf''e una funzione che accetta un numero variabile di argomenti e le conversioni in base al prototipo non sono possibili. – pmg

+0

C99 [6.5.2.2] (http://port70.net/~nsz/c/c99/n1256.html#6.5.2.2) ha la precedenza su questo. C'è una promozione intera a piedi. Forse ho avuto un conteggio errato - è probabilmente il paragrafo 5. – cha0site

1

Chiede informazioni sulla differenza reale. Quando parli di comportamento indefinito sei al livello di garanzia fornito dalle specifiche del linguaggio, è lontano dalla realtà. Per capire la vera differenza si prega di controllare questo frammento (naturalmente questo è UB ma è perfettamente definito dal compilatore preferito):

#include <stdio.h> 

int main() 
{ 
    int i1 = ~0; 
    int i2 = i1 >> 1; 
    unsigned u1 = ~0; 
    unsigned u2 = u1 >> 1; 
    printf("int   : %X -> %X\n", i1, i2); 
    printf("unsigned int: %X -> %X\n", u1, u2); 
} 
9

Non v'è alcuna differenza tra i due nel modo in cui vengono memorizzati nella memoria e registri, non esiste una versione firmata e non firmata dei registri int non ci sono informazioni firmate memorizzate con l'int, la differenza diventa rilevante solo quando si eseguono operazioni matematiche, ci sono la versione firmata e non firmata delle operazioni matematiche integrate nella CPU e la firma dice al compilatore quale versione utilizzare.

+0

Questa risposta è la più semplice –

1

Questo è piuttosto semplice. La rappresentazione binaria è la chiave che viene citata ma mai visualizzata. Non firmato in HEX se 0XFFFFFFF = codice macchina = 1111 1111 1111 1111 1111 1111 1111 1111 = 4,294,967,295 rappresentazioni positive di un numero. Questo è tutto a posto, ma abbiamo bisogno di un modo per rappresentare i numeri negativi. Quindi il cervello ha deciso di completarlo. Che cosa significa questo bene, insomma, hanno preso la cifra più a sinistra e ha deciso che, quando si tratta di un 1 (seguito da tutti quelli che fino a raggiungere il bit più significativo a sinistra) il numero sarà negativo se è 0 è positivo . Ora diamo un'occhiata a cosa succede 0000 0000 0000 0000 0000 0000 0000 0011 = 3. Ora continuiamo ad aggiungere a questo numero 0111 1111 1111 1111 1111 1111 1111 1111 = 2.147.483.645 il numero più alto positivo con un int firmato. Aggiungiamo 1 (qui si potrebbe voler cercare l'aggiunta binaria) dobbiamo portare l'intero fino in fondo. 1111 1111 1111 1111 1111 1111 1111 1110 = -1 Quindi credo che a breve potremmo dire la differenza è quella che permette per i numeri negativi l'altro non, che è a causa della bit di segno o sinistra più bit o il bit più significativo.

Problemi correlati