2013-05-12 23 views
16

Si consideri il seguente codice:Differenza tra char e firma in C++?

#include <iostream> 
#include <type_traits> 

int main(int argc, char* argv[]) 
{ 
    std::cout<<"std::is_same<int, int>::value = "<<std::is_same<int, int>::value<<std::endl; 
    std::cout<<"std::is_same<int, signed int>::value = "<<std::is_same<int, signed int>::value<<std::endl; 
    std::cout<<"std::is_same<int, unsigned int>::value = "<<std::is_same<int, unsigned int>::value<<std::endl; 
    std::cout<<"std::is_same<signed int, int>::value = "<<std::is_same<signed int, int>::value<<std::endl; 
    std::cout<<"std::is_same<signed int, signed int>::value = "<<std::is_same<signed int, signed int>::value<<std::endl; 
    std::cout<<"std::is_same<signed int, unsigned int>::value = "<<std::is_same<signed int, unsigned int>::value<<std::endl; 
    std::cout<<"std::is_same<unsigned int, int>::value = "<<std::is_same<unsigned int, int>::value<<std::endl; 
    std::cout<<"std::is_same<unsigned int, signed int>::value = "<<std::is_same<unsigned int, signed int>::value<<std::endl; 
    std::cout<<"std::is_same<unsigned int, unsigned int>::value = "<<std::is_same<unsigned int, unsigned int>::value<<std::endl; 
    std::cout<<"----"<<std::endl; 
    std::cout<<"std::is_same<char, char>::value = "<<std::is_same<char, char>::value<<std::endl; 
    std::cout<<"std::is_same<char, signed char>::value = "<<std::is_same<char, signed char>::value<<std::endl; 
    std::cout<<"std::is_same<char, unsigned char>::value = "<<std::is_same<char, unsigned char>::value<<std::endl; 
    std::cout<<"std::is_same<signed char, char>::value = "<<std::is_same<signed char, char>::value<<std::endl; 
    std::cout<<"std::is_same<signed char, signed char>::value = "<<std::is_same<signed char, signed char>::value<<std::endl; 
    std::cout<<"std::is_same<signed char, unsigned char>::value = "<<std::is_same<signed char, unsigned char>::value<<std::endl; 
    std::cout<<"std::is_same<unsigned char, char>::value = "<<std::is_same<unsigned char, char>::value<<std::endl; 
    std::cout<<"std::is_same<unsigned char, signed char>::value = "<<std::is_same<unsigned char, signed char>::value<<std::endl; 
    std::cout<<"std::is_same<unsigned char, unsigned char>::value = "<<std::is_same<unsigned char, unsigned char>::value<<std::endl; 
    return 0; 
} 

Il risultato è:

std::is_same<int, int>::value = 1 
std::is_same<int, signed int>::value = 1 
std::is_same<int, unsigned int>::value = 0 
std::is_same<signed int, int>::value = 1 
std::is_same<signed int, signed int>::value = 1 
std::is_same<signed int, unsigned int>::value = 0 
std::is_same<unsigned int, int>::value = 0 
std::is_same<unsigned int, signed int>::value = 0 
std::is_same<unsigned int, unsigned int>::value = 1 
---- 
std::is_same<char, char>::value = 1 
std::is_same<char, signed char>::value = 0 
std::is_same<char, unsigned char>::value = 0 
std::is_same<signed char, char>::value = 0 
std::is_same<signed char, signed char>::value = 1 
std::is_same<signed char, unsigned char>::value = 0 
std::is_same<unsigned char, char>::value = 0 
std::is_same<unsigned char, signed char>::value = 0 
std::is_same<unsigned char, unsigned char>::value = 1 

Il che significa che int e signed int sono considerati dello stesso tipo, ma non char e signed char. Perché ?

E se posso trasformare un char in signed char utilizzando make_signed, come fare il contrario (trasformare una signed char ad un char)?

+0

Interessante, sapevo che 'char' poteva essere firmato o non firmato, ma pensavo che sarebbe almeno equivalente a uno di quelli. – chris

+0

Possibile duplicato di [char! = (Char firmato), char! = (Char unsigned)] (https://stackoverflow.com/questions/436513/char-signed-char-char-unsigned-char) – jtbandes

risposta

12

È di progettazione, C++ standard dice char, signed char e unsigned char sono diversi tipi. Penso che tu possa usare il cast statico per la trasformazione.

5

Infatti, lo standard sta dicendo precisamente che char, char firmato e unsigned char sono di 3 tipi diversi. Un char è di solito 8 bit ma questo non è imposto dallo standard. Un numero a 8 bit può codificare 256 valori univoci; la differenza sta solo nel modo in cui questi 256 valori unici sono interpretati. Se si considera un valore a 8 bit come valore binario con segno, può rappresentare valori interi da -128 (tutti i numeri 1) a +127. Se lo consideri non firmato, può rappresentare valori da 0 a 255. Secondo lo standard C++, un char firmato può essere in grado di contenere valori da -127 a 127 (non -128!), Mentre un char senza segno è in grado di contenere valori Da 0 a 255.

Quando si converte un char in un int, il risultato è definito dall'implementazione! il risultato può ad es. essere -55 o 201 secondo l'implementazione della macchina del singolo carattere "É" (ISO 8859-1). In effetti, una CPU che contiene il carattere in una parola (16 bit) può memorizzare FFC9 o 00C9 o C900, o anche C9FF (in rappresentazioni grandi e piccoli endian). L'utilizzo di caratteri firmati o non firmati garantisce il risultato di conversione char a int.

8

Ci sono tre distinti tipi di carattere di base: char, firmato char e unsigned char. Sebbene esistano tre tipi di caratteri, esistono solo due rappresentazioni: firmate e non firmate. Il (normale) char utilizza una di queste rappresentazioni. Quale delle altre due rappresentazioni di caratteri è equivalente a chardipende dal compilatore.

In un tipo senza segno, tutti i bit rappresentano il valore. Ad esempio, un char senza segno a 8 bit può contenere i valori compresi tra 0 e 255 inclusi.

Lo standard non definisce la modalità di rappresentazione dei tipi di segno, ma specifica che l'intervallo deve essere equamente diviso tra valori positivi e negativi. Quindi un 8-bit char firmato è garantito per essere in grado di tenere i valori da -127 attraverso 127.


Così come decidere quale tipo da usare?

I calcoli utilizzando char di solito sono problematici.Char è configurato per impostazione predefinita su alcune macchine e non firmato su altri. Quindi non dovremmo usare (semplice) char in espressioni aritmetiche. Usalo solo per contenere caratteri. Se è necessario un numero intero minuscolo, specificare esplicitamente il carattere firmato o char senza segno.

+0

Lo so post è da molto tempo fa ma questa risposta è identica a un paragrafo in * C++ Primer *, secondo capitolo. – pkqxdd