Domanda
In C/C++, che cosa unsigned char
è usato per?In cosa è diverso da un normale char
?
Soluzione
In C++ ce ne sono tre distinto tipi di carattere:
char
signed char
unsigned char
Se stai utilizzando i tipi di carattere per testo, utilizzare il non qualificato char
:
- è il tipo di carattere letterale simile
'a'
O'0'
. - è il tipo che costituisce le stringhe C simili
"abcde"
Funziona anche come valore numerico, ma non è specificato se tale valore viene trattato come con segno o senza segno.Fai attenzione ai confronti dei caratteri attraverso le disuguaglianze, anche se ti limiti all'ASCII (0-127) sei quasi al sicuro.
Se stai utilizzando tipi di carattere come numeri, utilizzo:
signed char
, che ti dà almeno l'intervallo da -127 a 127.(da -128 a 127 è comune)unsigned char
, che ti dà almeno l'intervallo da 0 a 255.
"Almeno", perché lo standard C++ fornisce solo l'intervallo minimo di valori che ogni tipo numerico deve coprire. sizeof (char)
deve essere 1 (cioèun byte), ma in teoria un byte potrebbe essere composto ad esempio da 32 bit. sizeof
verrebbe comunque segnalato le sue dimensioni come 1
- nel senso che tu Potevo Avere sizeof (char) == sizeof (long) == 1
.
Altri suggerimenti
Ciò dipende dall'implementazione, poiché lo standard C NON definisce la presenza di segno di char
.A seconda della piattaforma, char potrebbe essere signed
O unsigned
, quindi è necessario richiederlo esplicitamente signed char
O unsigned char
se la tua implementazione dipende da questo.Basta usare char
se intendi rappresentare caratteri da stringhe, poiché ciò corrisponderà a ciò che la tua piattaforma inserisce nella stringa.
La differenza tra signed char
E unsigned char
è come ti aspetteresti.Sulla maggior parte delle piattaforme, signed char
sarà un numero in complemento a due a 8 bit compreso tra -128
A 127
, E unsigned char
sarà un numero intero senza segno a 8 bit (0
A 255
).Tieni presente che lo standard NON lo richiede char
i tipi hanno 8 bit, solo quello sizeof(char)
ritorno 1
.Puoi ottenere il numero di bit in un carattere con CHAR_BIT
In limits.h
.Ci sono poche, se non nessuna, piattaforme oggi in cui questo sarà qualcosa di diverso 8
, Anche se.
C'è un bel riassunto di questo problema Qui.
Come altri hanno già detto da quando ho pubblicato questo, è meglio usarlo int8_t
E uint8_t
se vuoi davvero rappresentare piccoli numeri interi.
Poiché ritengo che sia davvero necessario, voglio solo stabilire alcune regole di C e C++ (sono le stesse a questo riguardo).Primo, tutti i pezzi Di unsigned char
partecipare alla determinazione del valore di eventuali oggetti char senza segno.Secondo, unsigned char
è esplicitamente dichiarato senza segno.
Ora, ho discusso con qualcuno su cosa succede quando converti il valore -1
di tipo int a unsigned char
.Ha rifiutato l'idea che il risultato unsigned char
ha tutti i bit impostati su 1, perché era preoccupato per la rappresentazione dei segni.Ma non è necessario.Ne consegue immediatamente che la conversione fa ciò che è previsto:
Se il nuovo tipo non è firmato, il valore viene convertito aggiungendo o sottraendo ripetutamente uno più del valore massimo che può essere rappresentato nel nuovo tipo fino a quando il valore non è nell'intervallo del nuovo tipo.(
6.3.1.3p2
in una bozza C99)
Questa è una descrizione matematica.Il C++ lo descrive in termini di calcolo modulo, che cede alla stessa regola.Comunque, cos'è non garantito è che tutti i bit siano numeri interi -1
sono uno prima della conversione.Quindi, cosa abbiamo per poter affermare che il risultato unsigned char
ha tutto suo CHAR_BIT
bit ruotati a 1?
- Tutti i bit partecipano alla determinazione del suo valore, ovvero nell'oggetto non sono presenti bit di riempimento.
- Aggiunta solo una volta
UCHAR_MAX+1
A-1
produrrà un valore nell'intervallo, vale a direUCHAR_MAX
Questo è abbastanza, in realtà!Quindi ogni volta che vuoi avere un unsigned char
avendo tutti i suoi pezzi uno, lo fai
unsigned char c = (unsigned char)-1;
Ne consegue anche che una conversione è non semplicemente troncando i bit di ordine superiore.L'evento fortunato per complemento a due è che lì si tratta solo di un troncamento, ma lo stesso non è necessariamente vero per altre rappresentazioni di segni.
Come ad esempio gli usi di carattere non firmato:
carattere non firmato è spesso utilizzato nella computer grafica, che molto spesso (anche se non sempre) assegna un singolo byte a ciascuna componente di colore.È comune vedere un colore RGB (o RGBA) rappresentato come 24 (o 32) bit, ciascuno carattere non firmato.Da carattere non firmato i valori rientrano nell'intervallo [0,255], i valori sono generalmente interpretati come:
- 0 indica la totale mancanza di una determinata componente cromatica.
- 255 che significa 100% di un dato pigmento di colore.
Quindi ti ritroveresti con il rosso RGB come (255,0,0) -> (100% rosso, 0% verde, 0% blu).
Perché non usare a firmato car?L'aritmetica e lo spostamento dei bit diventano problematici.Come già spiegato, a firmato carl'intervallo di è essenzialmente spostato di -128.Un metodo molto semplice e ingenuo (per lo più inutilizzato) per convertire RGB in scala di grigi è quello di fare una media di tutti e tre i componenti del colore, ma questo incontra problemi quando i valori dei componenti del colore sono negativi.Il rosso (255, 0, 0) ha una media di (85, 85, 85) quando si utilizza carattere non firmato aritmetica.Tuttavia, se i valori fossero firmato cars (127,-128,-128), finiremo con (-99, -99, -99), che sarebbe (29, 29, 29) nel nostro carattere non firmato spazio, il che non è corretto.
Se vuoi usare un carattere come un piccolo numero intero, il modo più sicuro per farlo è con int8_t
E uint8_t
tipi.
signed char
ha un intervallo compreso tra -128 e 127; unsigned char
ha un intervallo compreso tra 0 e 255.
char
sarà equivalente a Signed Char o Unsigned Char, a seconda del compilatore, ma è un tipo distinto.
Se stai usando stringhe in stile C, usa semplicemente char
.Se è necessario utilizzare i caratteri per l'aritmetica (piuttosto raro), specificare esplicitamente firmato o non firmato per la portabilità.
char
E unsigned char
non è garantito che siano di tipo a 8 bit su tutte le piattaforme: è garantito che siano a 8 bit o superiori.Alcune piattaforme lo hanno Byte a 9 bit, 32 bit o 64 bit.Tuttavia, le piattaforme più comuni oggi (Windows, Mac, Linux x86, ecc.) hanno byte a 8 bit.
In termini di valori diretti viene utilizzato un carattere regolare quando è noto che i valori sono compresi tra CHAR_MIN
E CHAR_MAX
mentre un carattere senza segno fornisce il doppio dell'intervallo sul lato positivo.Ad esempio, se CHAR_BIT
è 8, l'intervallo di normale char
è garantito solo che sia [0, 127] (perché può essere firmato o non firmato) mentre unsigned char
sarà [0, 255] e signed char
sarà [-127, 127].
In termini di utilizzo, gli standard consentono di convertire direttamente gli oggetti POD (plain old data) in un array di caratteri senza segno.Ciò consente di esaminare la rappresentazione e i modelli di bit dell'oggetto.La stessa garanzia di gioco di parole sicuro non esiste per char o char con segno.
unsigned char
accetta solo valori positivi....like 0 A 255
mentre
signed char
assume valori sia positivi che negativi....come -128 A +127
Un carattere senza segno è un valore byte (senza segno) (da 0 a 255).Potresti pensare a "char" in termini di "carattere", ma in realtà è un valore numerico.Il "carattere" regolare è firmato, quindi hai 128 valori e questi valori vengono mappati ai caratteri utilizzando la codifica ASCII.Ma in entrambi i casi, ciò che stai memorizzando in memoria è un valore in byte.
Se ti piace usare vari tipi di lunghezza e segnatura specifici, probabilmente stai meglio con uint8_t, int8_t, uint16_t, ecc. semplicemente perché fanno esattamente quello che dicono.
Un carattere senza segno utilizza il bit riservato al segno di un carattere regolare come un altro numero.Ciò modifica l'intervallo in [0 - 255] anziché [-128 - 127].
Generalmente i caratteri senza segno vengono utilizzati quando non si desidera un segno.Ciò farà la differenza quando si eseguono operazioni come lo spostamento di bit (lo spostamento estende il segno) e altre cose quando si ha a che fare con un carattere come byte anziché utilizzarlo come numero.
il carattere non firmato è il cuore di tutti i piccoli inganni.In quasi TUTTI i compilatori per TUTTE le piattaforme un carattere senza segno è semplicemente un BYTE.Un numero intero senza segno di (solitamente) 8 bit.che può essere trattato come un piccolo numero intero o un pacchetto di bit.
Inoltre, come ha detto qualcun altro, lo standard non definisce il segno di un carattere.quindi hai 3 tipi "char" distinti:char, char firmato, char non firmato.
Ho trovato qualche ricerca su Google Questo, dove le persone hanno discusso di questo.
Un carattere senza segno è fondamentalmente un singolo byte.Quindi, lo utilizzeresti se hai bisogno di un byte di dati (ad esempio, forse vuoi usarlo per attivare e disattivare i flag da passare a una funzione, come spesso avviene nell'API di Windows).
citato dal libro "The C Programming Laugage":
Il qualificatore signed
O unsigned
può essere applicato a char o a qualsiasi numero intero.I numeri non firmati sono sempre positivi o zero e obbediscono alle leggi del modulo aritmetico 2^n, dove n è il numero di bit nel tipo.Quindi, ad esempio, se i caratteri sono 8 bit, le variabili di caratteri non firmate hanno valori tra 0 e 255, mentre i caratteri firmati hanno valori tra -128 e 127 (in una macchina per il complemento a due.) Se i caratteri semplici sono firmati o non firmati -I caratteri dipendenti, ma stampabili sono sempre positivi.
unsigned char accetta solo valori positivi:Da 0 a 255 Char firmato richiede valori positivi e negativi:da -128 a +127