Em C / C ++, para que unsigned char
é usado? Como é diferente de um regular char
?
No C ++, existem três tipos de caracteres distintos :
char
signed char
unsigned char
Se você estiver usando tipos de caracteres para texto , use o não qualificado char
:
'a'
ou '0'
."abcde"
Também funciona como um valor numérico, mas não é especificado se esse valor é tratado como assinado ou não. Cuidado com as comparações de caracteres por meio de desigualdades - embora se você se limitar a ASCII (0-127), estará quase seguro.
Se você estiver usando tipos de caracteres como números , use:
signed char
, que fornece pelo menos o intervalo de -127 a 127. (-128 a 127 é comum)unsigned char
, que fornece pelo menos o intervalo de 0 a 255."Pelo menos", porque o padrão C ++ fornece apenas o intervalo mínimo de valores que cada tipo numérico é necessário para cobrir. sizeof (char)
é necessário que seja 1 (ou seja, um byte), mas em teoria um byte pode ter, por exemplo, 32 bits. sizeof
ainda seria informar seu tamanho como1
- o que você poderia ter sizeof (char) == sizeof (long) == 1
.
sizeof
porque não é uma função, mas um operador. É imho um estilo ainda melhor para omitir os parênteses quando se assume o tamanho de uma variável.sizeof *p
ousizeof (int)
. Isso deixa claro rapidamente se se aplica a um tipo ou variável. Da mesma forma, também é redundante colocar parênteses depoisreturn
. Não é uma função.char
: é o tipo de literal de caractere como'a'
ou'0'
." é verdadeiro em C ++, mas não em C. Em C,'a'
é umint
.Isso depende da implementação, pois o padrão C NÃO define a assinatura de
char
. Dependendo da plataforma, char pode sersigned
ouunsigned
, portanto, você precisa solicitar explicitamentesigned char
ouunsigned char
se sua implementação depende disso. Basta usarchar
se você pretende representar caracteres de cadeias, pois isso corresponderá ao que sua plataforma coloca na cadeia.A diferença entre
signed char
eunsigned char
é como você esperaria. Na maioria das plataformas,signed char
haverá um número de complemento de dois bits de 8 bits que varia de-128
a127
eunsigned char
será um número inteiro não assinado de 8 bits (0
para255
). Observe que o padrão NÃO exige que oschar
tipos tenham 8 bits, apenas essesizeof(char)
retorno1
. Você pode obter o número de bits em um caractere comCHAR_BIT
inlimits.h
. Hoje existem poucas plataformas, se houver alguma, em que isso será algo diferente8
.Há um bom resumo dessa questão aqui .
Como outros já mencionaram desde que eu postei isso, é melhor você usar
int8_t
euint8_t
se realmente deseja representar números inteiros pequenos.fonte
CHAR_BIT
é necessário ter pelo menos 8 bits pelo padrão.Porque eu sinto que é realmente necessário, eu só quero declarar algumas regras de C e C ++ (elas são as mesmas a esse respeito). Primeiro, todos os bits de
unsigned char
participar na determinação do valor se qualquer objeto sem assinatura char. Segundo,unsigned char
é explicitamente declarado sem sinal.Agora, tive uma discussão com alguém sobre o que acontece quando você converte o valor
-1
do tipo intunsigned char
. Ele recusou a ideia de que o resultadounsigned char
tenha todos os bits definidos como 1, porque estava preocupado com a representação de sinais. Mas ele não precisa. Imediatamente após esta regra, a conversão faz o que se destina:Essa é uma descrição matemática. O C ++ o descreve em termos de módulo de cálculo, que gera a mesma regra. De qualquer forma, o que não é garantido é que todos os bits no número inteiro
-1
são um antes da conversão. Então, o que temos para afirmar que o resultadounsigned char
tem todos os seusCHAR_BIT
bits voltados para 1?UCHAR_MAX+1
para-1
produzirá um valor no intervalo, ou seja,UCHAR_MAX
Já chega, na verdade! Então, sempre que você quiser
unsigned char
ter todos os seus bits um, façaSegue-se também que uma conversão não está apenas truncando bits de ordem superior. O evento feliz para o complemento de dois é que é apenas um truncamento, mas o mesmo não é necessariamente verdadeiro para outras representações de signos.
fonte
UCHAR_MAX
?(unsigned type)-1
é algum tipo de linguagem.~0
não é.int x = 1234
echar *y = &x
. Representação binária de1234
é00000000 00000000 00000100 11010010
. Minha máquina é pouco endian e, portanto, a reverte e armazena na memória que o11010010 00000100 00000000 00000000
LSB vem em primeiro lugar. Agora parte principal. se eu usarprintf("%d" , *p)
.printf
lerá primeiro byte11010010
apenas a saída é,-46
mas11010010
é210
por isso que ela é impressa-46
. Estou realmente confuso, eu acho que algum char para promoção inteira está fazendo algo, mas eu não sei.Como, por exemplo, usos de caracteres não assinados :
unsigned char
é frequentemente usado em computação gráfica, que muitas vezes (embora nem sempre) atribui um único byte a cada componente de cor. É comum ver uma cor RGB (ou RGBA) representada como 24 (ou 32) bits, cada umunsigned char
. Como osunsigned char
valores caem no intervalo [0,255], os valores são geralmente interpretados como:Assim, você terminaria com o vermelho RGB como (255,0,0) -> (100% vermelho, 0% verde, 0% azul).
Por que não usar um
signed char
? A aritmética e a troca de bits se tornam problemáticas. Como já explicado,signed char
o intervalo de a é essencialmente deslocado por -128. Um método muito simples e ingênuo (principalmente não utilizado) para converter RGB em escala de cinza é calcular a média dos três componentes de cores, mas isso ocorre quando os valores dos componentes de cores são negativos. A média de vermelho (255, 0, 0) é de (85, 85, 85) ao usarunsigned char
aritmética. No entanto, se os valores fossemsigned char
s (127, -128, -128), terminaríamos com (-99, -99, -99), que seria (29, 29, 29) em nossounsigned char
espaço, o que está incorreto .fonte
Se você deseja usar um caractere como um número inteiro pequeno, a maneira mais segura de fazer isso é com os tipos
int8_t
euint8_t
fonte
int8_t
euint8_t
são opcionais e não definida em arquiteturas onde o tamanho byte não é exatamente 8 bits. Por outro lado,signed char
eunsigned char
estão sempre disponíveis e garantidos para conter pelo menos 8 bits. Pode ser uma maneira comum , mas não a mais segura .signed char
eunsigned char
? Ou você recomendaria uma alternativa melhor "mais segura" nesse caso específico? Por exemplo, ficar com os tipos inteiros "reais"signed int
e,unsigned int
por algum motivo?signed char
eunsigned char
é portátil para todas as implementações em conformidade e economizará espaço de armazenamento, mas poderá causar algum aumento no tamanho do código. Em alguns casos, economizaria mais espaço de armazenamento armazenando pequenos valores em campos de bits ou bits únicos de tipos inteiros regulares. Não há resposta absoluta para essa pergunta, a pertinência dessa abordagem depende do caso específico em questão. E esta resposta não aborda a questão de qualquer maneira.unsigned char
leva apenas valores positivos .... como 0 a 255enquanto que
signed char
leva valores positivos e negativos .... como -128 a +127fonte
char
eunsigned char
não são garantidos tipos de 8 bits em todas as plataformas - eles têm 8 bits ou mais. Algumas plataformas têm bytes de 9, 32 ou 64 bits . No entanto, as plataformas mais comuns hoje em dia (Windows, Mac, Linux x86 etc.) possuem bytes de 8 bits.fonte
signed char
tem um intervalo de -128 a 127;unsigned char
tem intervalo de 0 a 255.char
será equivalente a um caractere assinado ou não assinado, dependendo do compilador, mas é um tipo distinto.Se você estiver usando seqüências de caracteres em estilo C, use
char
. Se você precisar usar chars para aritmética (bastante raro), especifique assinado ou não assinado explicitamente para portabilidade.fonte
An
unsigned char
é um valor de byte não assinado (0 a 255). Você pode estar pensandochar
em termos de ser um "personagem", mas é realmente um valor numérico. O regularchar
é assinado, então você tem 128 valores e esses valores são mapeados para caracteres usando a codificação ASCII. Mas em ambos os casos, o que você está armazenando na memória é um valor de byte.fonte
Em termos de valores diretos, um caractere comum é usado quando se sabe que os valores estão entre
CHAR_MIN
eCHAR_MAX
enquanto um caractere não assinado fornece o dobro do intervalo na extremidade positiva. Por exemplo, seCHAR_BIT
for 8, o intervalo de regularchar
é garantido apenas como [0, 127] (porque pode ser assinado ou não assinado) enquantounsigned char
será [0, 255] esigned char
será [-127, 127].Em termos de para que é usado, os padrões permitem que objetos de POD (dados antigos simples) sejam diretamente convertidos em uma matriz de caracteres não assinados. Isso permite que você examine a representação e os padrões de bits do objeto. A mesma garantia de punção de tipo seguro não existe para char ou char assinado.
fonte
unsigned char
, e não uma matriz especificamente, & qualquer "conversão" só é formalmente definido por cópia do objecto para uma verdadeira, declarado gama deunsigned char
&, em seguida, inspeccionar o último. Não está claro se o OR pode ser reinterpretado diretamente como uma matriz, com as permissões para a aritmética do ponteiro que isso implicaria, ou seja, se "seqüência"==
"matriz" nesse uso. Há um problema central nº 1701 aberto na esperança de esclarecer isso. Felizmente, como essa ambiguidade está realmente me incomodando recentemente.unsigned char
da++ptr
sala de cirurgia e continuar usando a partir daí para ler todos os bytes ... mas AFAICT, não é definido especificamente como permitido, então estamos resta inferir que é 'provavelmente OK' de muitas outras passagens (e de muitas maneiras, a mera existência dememcpy
) no Padrão, semelhante a um quebra-cabeça. O que não é o ideal. Bem, talvez a redação melhore eventualmente. Aqui está o problema do CWG que mencionei, mas sem espaço para vincular - open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1701unsigned char
é o coração de todos os truques. Em quase TODO o compilador para TODA a plataforma, umunsigned char
é simplesmente um byte e um número inteiro não assinado de (geralmente) 8 bits que podem ser tratados como um número inteiro pequeno ou um pacote de bits.Além disso, como alguém já disse, o padrão não define o sinal de um caractere. então você tem 3 diferentes
char
tipos:char
,signed char
,unsigned char
.fonte
Se você gosta de usar vários tipos de comprimento e de assinatura específica, você é provavelmente melhor fora com
uint8_t
,int8_t
,uint16_t
, etc, simplesmente porque eles fazem exatamente o que eles dizem.fonte
Alguns pesquisadores descobriram isso , onde as pessoas discutiram sobre isso.
Um caracter não assinado é basicamente um byte único. Portanto, você usaria isso se precisar de um byte de dados (por exemplo, talvez você queira usá-lo para ativar e desativar sinalizadores para serem passados para uma função, como costuma ser feito na API do Windows).
fonte
Um caractere não assinado usa o bit reservado para o sinal de um caractere regular como outro número. Isso altera o intervalo para [0 - 255] em oposição a [-128 - 127].
Geralmente, caracteres não assinados são usados quando você não deseja um sinal. Isso fará a diferença ao fazer coisas como bits de deslocamento (shift estende o sinal) e outras coisas ao lidar com um char como um byte, em vez de usá-lo como um número.
fonte
unsigned char
aceita apenas valores positivos: 0 a 255, enquantosigned char
aceita valores positivos e negativos: -128 a +127.fonte
citado do livro "the c programming laugage":
O qualificador
signed
ouunsigned
pode ser aplicado a char ou a qualquer número inteiro. números não assinados são sempre positivos ou zero e obedecem às leis do módulo aritmético 2 ^ n, em que n é o número de bits no tipo. Assim, por exemplo, se caracteres são 8 bits, variáveis de caracteres não assinadas têm valores entre 0 e 255, enquanto caracteres assinados têm valores entre -128 e 127 (em uma máquina de complemento de dois). Se caracteres simples são assinados ou não é uma máquina independentes, mas os caracteres imprimíveis são sempre positivos.fonte
signed char
eunsigned char
ambos representam 1 byte, mas eles têm intervalos diferentes.Em
signed char
se considerarmoschar letter = 'A'
, 'A' é representar binário de 65 emASCII/Unicode
, Se 65 pode ser armazenado, -65 também podem ser armazenados. Não há valores binários negativosASCII/Unicode
, pois não há necessidade de se preocupar com valores negativos.Exemplo
Resultado -:
fonte