2012-12-11 16 views
9

Quando si conserva "array di byte" (macchie ...) è meglio utilizzare char o unsigned char per le voci (anche noto come unsigned charuint8_t)? (Lo standard dice che sizeof di entrambi è precisamente 1 byte.)Char vs unsigned char per gli array di byte

Ha importanza? O uno è più conveniente o prevalente rispetto agli altri? Forse, quali librerie come Boost usano?

+2

@nightcracker Forse, potresti indicare il duplicato? – Cartesius00

+0

Dupe con https://stackoverflow.com/questions/653336/ – kebs

risposta

10

Se char è firmato, quindi eseguire l'aritmetica su un valore di byte con il bit alto impostato comporterà l'estensione del segno quando si promuove a int; così, ad esempio:

char c = '\xf0'; 
int res = (c << 24) | (c << 16) | (c << 8) | c; 

darà 0xfffffff0 anziché 0xf0f0f0f0. Questo può essere evitato mascherando con 0xff.

char potrebbe essere preferibile se si interfaccia con librerie che lo utilizzano invece di unsigned char.

Si noti che un cast da char * a/da unsigned char * è sempre sicuro (3.9p2). Una ragione filosofica favorire unsigned char è che 3.9p4 nello standard favorisce, almeno per rappresentare array di byte che potrebbe tenere rappresentazioni della memoria di oggetti:

La rappresentazione oggetto di un oggetto di tipo T è la sequenza di Nunsigned char oggetti rilevati dall'oggetto del tipo T, dove N equivale a sizeof(T).

+0

Oh, bella cattura davvero. +1 – Cartesius00

1

Teoricamente, la dimensione di un byte in C++ dipende dalla piattaforma compilatore-impostazioni e bersaglio, ma è garantito essere almeno di 8 bit, che spiega perché sizeof(uint8_t) è richiesto di essere 1.

Ecco più precisamente ciò che la norma ha da dire in proposito

§1.71

l'unità di memorizzazione fondamentale nel modello di memoria C++ è il byte. Un byte è almeno abbastanza grande da contenere qualsiasi membro del set di caratteri di esecuzione di base (2.3) e le unità di codice a otto bit del modulo di codifica UTF-8 ed è composto da una sequenza contigua di bit, il il numero di cui è definito dall'implementazione. Il bit meno significativo è chiamato bit di ordine inferiore; il bit più significativo è chiamato bit di ordine superiore. La memoria disponibile per un programma C++ consiste di una o più sequenze di byte contigui. Ogni byte ha un indirizzo univoco.

Quindi, se si sta lavorando su un hardware speciale in cui i byte non sono 8 bit, può fare una differenza pratica. Altrimenti, direi che è una questione di gusti e quali informazioni vuoi comunicare attraverso la scelta del tipo.

0

non fa alcuna differenza pratica, anche se forse dal punto di vista della leggibilità è più chiaro se il tipo è unsigned char che implica valori 0..255.

0

Uno degli altri problemi con l'utilizzo potenziale di un valore con segno per BLOB è che il valore dipenderà dalla rappresentazione del segno, che non fa parte dello standard. Quindi, è più facile invocare un comportamento indefinito.

Per esempio ...

signed char x = 0x80; 
int y = 0xffff00ff; 

y |= (x << 8); // UB 

Il valore aritmetico reale sarebbe anche strettamente dipenderà complemento a due, che può dare alcune persone sorprese. L'utilizzo di unsigned in modo esplicito evita questi problemi.