it-swarm.it

Cos'è un char non firmato?

In C/C++, a cosa serve unsigned char? In che modo è diverso da un char regolare?

427
Landon Kuhn

In C++, ci sono tre distinti tipi di caratteri:

  • char
  • signed char
  • unsigned char

Se stai usando i tipi di caratteri per text , usa il char non qualificato:

  • è il tipo di caratteri letterali come 'a' o '0'.
  • è il tipo che costituisce le stringhe C come "abcde"

Funziona anche come valore numerico, ma non è specificato se quel valore è considerato come firmato o non firmato. Fai attenzione ai confronti tra i personaggi attraverso le disuguaglianze, anche se ti limiti a ASCII (0-127) sei quasi sicuro.

Se stai usando tipi di caratteri come numbers , usa:

  • signed char, che fornisce almeno l'intervallo da -127 a 127. (Da -128 a 127 è comune)
  • unsigned char, che fornisce almeno l'intervallo da 0 a 255.

"Almeno", perché lo standard C++ fornisce solo l'intervallo minimo di valori che ciascun tipo numerico deve coprire. sizeof (char) è richiesto per essere 1 (cioè un byte), ma un byte potrebbe in teoria essere per esempio 32 bit.sizeof DOVREBBE COMUNQUE RIPORTARE LE SUE DIMENSIONI COME 1- che significa che potrebbe avere sizeof (char) == sizeof (long) == 1.

509
Fruny

Questo dipende dall'implementazione, poiché lo standard C NON definisce la firma di char. A seconda della piattaforma, char può essere signed o unsigned, quindi è necessario chiedere esplicitamente signed char o unsigned char se l'implementazione dipende da esso. Usa solo 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 ci si aspetterebbe. Sulla maggior parte delle piattaforme, signed char sarà un numero di complemento a due bit di 8 bit che va da -128 a 127, e unsigned char sarà un numero intero senza segno a 8 bit (0 to 255). Nota che lo standard NON richiede che i tipi char abbiano 8 bit, solo che sizeof(char) restituisce 1. È possibile ottenere il numero di bit in un carattere con CHAR_BIT in limits.h. Oggi ci sono poche piattaforme se questa sarà diversa da 8.

C'è un bel riassunto di questo numero qui .

Come altri hanno menzionato da quando ho postato questo, è meglio usare int8_t e uint8_t se si vogliono rappresentare interi piccoli.

79
Todd Gamblin

Perché sento che è davvero richiesto, voglio solo enunciare alcune regole di C e C++ (sono le stesse in questo senso). Innanzitutto, tutti i bit di unsigned char partecipano alla determinazione del valore se qualsiasi oggetto char non firmato. In secondo luogo, unsigned char è esplicitamente dichiarato non firmato.

Ora, ho avuto una discussione con qualcuno su cosa succede quando converti il ​​valore -1 di tipo int in unsigned char. Ha rifiutato l'idea che il unsigned char risultante abbia tutti i suoi bit impostati su 1, perché era preoccupato per la rappresentazione del segno. Ma lui non deve. Sta immediatamente seguendo questa regola che la conversione fa ciò che è inteso:

Se il nuovo tipo non è firmato, il valore viene convertito aggiungendo o sottraendo ripetutamente un valore superiore al valore massimo che può essere rappresentato nel nuovo tipo finché il valore non si trova nell'intervallo del nuovo tipo. (6.3.1.3p2 in una bozza C99)

Questa è una descrizione matematica. C++ lo descrive in termini di modulo di calcolo, che produce la stessa regola. Ad ogni modo, ciò che è non garantito è che tutti i bit nell'intero -1 sono uno prima della conversione. Quindi, che cosa abbiamo in modo che possiamo affermare che il unsigned char risultante ha tutti i suoi bit CHAR_BIT convertiti in 1?

  1. Tutti i bit partecipano alla determinazione del suo valore, ovvero nessun bit di riempimento si verifica nell'oggetto.
  2. L'aggiunta di una sola volta UCHAR_MAX+1 a -1 produrrà un valore nell'intervallo, ovvero UCHAR_MAX

Questo è abbastanza, in realtà! Quindi ogni volta che vuoi avere un unsigned char che abbia tutti i suoi bit uno, lo fai

unsigned char c = (unsigned char)-1;

Ne consegue anche che una conversione è non solo troncando i bit di ordine superiore. L'evento fortunato per il complemento a due è che è solo un troncamento lì, ma lo stesso non è necessariamente vero per altre rappresentazioni di segni.

35

Come ad esempio gli usi di unsigned char :

unsigned char è spesso usato in computer graphics, che molto spesso (anche se non sempre) assegna un singolo byte a ciascun componente di colore. È comune vedere un colore RGB (o RGBA) rappresentato come 24 (o 32) bit, ciascuno un unsigned char . Dato che unsigned char values ​​rientrano nell'intervallo [0,255], i valori sono tipicamente interpretati come:

  • 0 significa una mancanza totale di un dato componente di colore.
  • 255 indica il 100% di un dato pigmento di colore.

Così si finirebbe con RGB rosso come (255,0,0) -> (100% rosso, 0% verde, 0% blu).

Perché non usare un signed char ? L'aritmetica e il cambio di bit diventano problematici. Come già spiegato, un intervallo di signed char è sostanzialmente spostato di -128. Un metodo molto semplice e ingenuo (per lo più inutilizzato) per convertire da RGB a scala di grigi è la media di tutti e tre i componenti del colore, ma questo si verifica quando i valori dei componenti del colore sono negativi. Red (255, 0, 0) medie a (85, 85, 85) quando si utilizza unsigned char arithmetic. Tuttavia, se i valori fossero signed char s (127, -128, -128), avremmo finito con (-99, -99, -99), che sarebbe (29, 29, 29 ) nel nostro unsigned char space, che non è corretto.

24
Zachary Garrett

Se si desidera utilizzare un carattere come un numero intero piccolo, il modo più sicuro per farlo è con i tipi int8_tand uint8_t.

12
jbleners

signed char ha intervallo da -128 a 127; unsigned char ha intervallo da 0 a 255.

char sarà equivalente al char firmato o al char unsigned, a seconda del compilatore, ma è un tipo distinto.

Se stai usando le stringhe in stile C, usa char. Se è necessario utilizzare i caratteri per l'aritmetica (piuttosto raro), specificare esplicitamente la firma o la firma per la portabilità.

5
James Hopkin

char e unsigned char non sono garantiti come tipi a 8 bit su tutte le piattaforme, sono garantiti per essere 8-bit o più grandi. Alcune piattaforme hanno 9 bit, 32 bit o 64 bit byte . Tuttavia, le piattaforme più comuni oggi (Windows, Mac, Linux x86, ecc.) Hanno byte da 8 bit.

5
bk1e

In termini di valori diretti viene utilizzato un carattere normale quando i valori sono noti tra CHAR_MIN e CHAR_MAX mentre un char senza segno fornisce il doppio dell'intervallo sul lato positivo. Ad esempio, se CHAR_BIT è 8, l'intervallo di char regolare è garantito solo per [0, 127] (perché può essere firmato o non firmato) mentre unsigned char sarà [0, 255] e signed char sarà [-127, 127 ].

In termini di ciò per cui è utilizzato, gli standard consentono agli oggetti del POD (semplici vecchi dati) di essere convertiti direttamente in una matrice di caratteri non firmati. Ciò consente di esaminare la rappresentazione e i pattern di bit dell'oggetto. La stessa garanzia di punizioni di tipo sicuro non esiste per char o char firmato.

4
Julienne Walker

unsigned char accetta solo valori positivi .... come 0 a 255

mentre

signed char accetta valori sia positivi che negativi .... come -128 a +127

4
munna

Un char senza segno è un valore di byte (senza segno) (da 0 a 255). Potresti pensare a "char" in termini di "personaggio", ma in realtà è un valore numerico. Il "char" normale è firmato, quindi hai 128 valori, e questi valori si associano ai caratteri usando la codifica ASCII. Ma in entrambi i casi, ciò che stai memorizzando è un valore in byte.

3
Zac Gochenour

Se ti piace usare vari tipi di lunghezza e firma specifici, probabilmente stai meglio con uint8_t, int8_t, uint16_t, ecc semplicemente perché fanno esattamente quello che dicono.

2
Dark Shikari

Un char senza segno utilizza il bit che è riservato per il segno di un carattere normale come un altro numero. Ciò cambia l'intervallo su [0 - 255] rispetto a [-128 - 127].

I caratteri generalmente non firmati vengono utilizzati quando non si desidera un segno. Questo farà la differenza quando si fanno cose come spostare i bit (shift estende il segno) e altre cose quando si ha a che fare con un char come byte piuttosto che usarlo come un numero.

2
JasonOfEarth

il char non firmato è il cuore di tutti i trucchetti. In quasi tutti i compilatori per tutte le piattaforme, un char 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.

In aggiunta, come ha detto qualcun altro, lo standard non definisce il segno di un carattere. quindi hai 3 diversi tipi "char": char, signed char, unsigned char.

2
ugasoft

Alcuni googling trovato questo , dove le persone hanno avuto una discussione su questo.

Un char senza segno è fondamentalmente un singolo byte. Quindi, dovresti usarlo se hai bisogno di un byte di dati (ad esempio, forse vuoi usarlo per impostare i flag on e off per essere passati a una funzione, come spesso accade nell'API di Windows).

1
dbrien

il carattere non firmato prende solo valori positivi: da 0 a 255 caratteri scritti prende valori positivi e negativi: da -128 a +127

0
NL628

citato dal libro "the c programming laugage":

Il qualificatore signed o unsigned può essere applicato a char o qualsiasi intero. i numeri senza segno sono sempre positivi o pari a zero e rispettano le leggi dell'aritmetico modulo 2 ^ n, dove n è il numero di bit nel tipo. Quindi, ad esempio, se i caratteri sono 8 bit, le variabili char non firmate hanno valori compresi tra 0 e 255, mentre i caratteri firmati hanno valori compresi tra -128 e 127 (in una macchina a complemento di due). Se i caratteri semplici sono firmati o non firmati è macchina -dipendenti, ma i caratteri stampabili sono sempre positivi.

0
ZhaoGang