it-swarm-pt.tech

O que é um caracter não assinado?

Em C/C++, para que um unsigned char é usado? Como é diferente de um char regular?

433
Landon Kuhn

Em C++, existem três tipos de caracteres distintos :

  • charname__
  • signed char
  • unsigned char

Se você estiver usando tipos de caracteres para texto , use o unsalified charname__:

  • é o tipo de literais de caracteres como 'a' ou '0'.
  • é o tipo que compõe strings C como "abcde"

Ele também funciona como um valor numérico, mas não é especificado se esse valor é tratado como assinado ou não assinado. Cuidado com comparações de personagens através de desigualdades - embora se você se limita a ASCII (0-127) você está quase seguro.

Se você estiver usando tipos de caracteres como números , use:

  • signed char, que dá a você pelo menos o intervalo de -127 a 127. (-128 a 127 é comum)
  • unsigned char, que dá a você 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 para ser 1 (ou seja, um byte), mas um byte poderia, em teoria, ser por exemplo 32 bits. sizeofNAME__ AINDA SERIA REPORTAR SEU TAMANHO COMO 1 - significando que você poderia ter sizeof (char) == sizeof (long) == 1.

513
Fruny

Isso depende da implementação, pois o padrão C NÃO define a assinatura de char. Dependendo da plataforma, char pode ser signed ou unsigned, portanto, é necessário solicitar explicitamente signed char ou unsigned char se sua implementação depender disso. Apenas use char se você pretende representar caracteres de strings, pois isso corresponderá ao que sua plataforma coloca na string.

A diferença entre signed char e unsigned char é a esperada. Na maioria das plataformas, signed char será um complemento de dois bits de 8 bits variando de -128 para 127, e unsigned char será um inteiro sem sinal de 8 bits (0 para 255). Observe que o padrão NÃO exige que os tipos char tenham 8 bits, somente que sizeof(char) retorne 1. Você pode obter o número de bits em um char com CHAR_BIT em limits.h. Existem poucas ou nenhumas plataformas hoje em que isto será algo diferente de 8, no entanto.

Há um bom resumo desta questão aqui .

Como outros já mencionaram desde que eu postei isso, é melhor você usar int8_t e uint8_t se realmente quiser representar inteiros pequenos.

81
Todd Gamblin

Porque eu sinto que é realmente chamado, eu só quero declarar algumas regras de C e C++ (eles são os mesmos a este respeito). Primeiro, todos os bits de unsigned char participam na determinação do valor se qualquer objeto char não assinado. Em segundo lugar, unsigned char é explicitamente declarado como não assinado.

Agora, eu tive uma discussão com alguém sobre o que acontece quando você converte o valor -1 do tipo int para unsigned char. Ele recusou a idéia de que o unsigned char resultante tenha todos os bits definidos como 1, porque ele estava preocupado com a representação do sinal. Mas ele não precisa. É imediatamente após esta regra que a conversão faz o que é pretendido:

Se o novo tipo não estiver assinado, o valor será convertido, adicionando ou subtraindo repetidamente um a mais que o valor máximo que pode ser representado no novo tipo até que o valor esteja no intervalo do novo tipo. (6.3.1.3p2 em um rascunho C99)

Essa é uma descrição matemática. C++ descreve-o em termos de módulo de cálculo, que produz a mesma regra. De qualquer forma, o que é não garantido é que todos os bits no inteiro -1 são um antes da conversão. Então, o que temos para que possamos afirmar que o unsigned char resultante tem todos os bits CHAR_BIT transformados em 1?

  1. Todos os bits participam na determinação de seu valor - ou seja, nenhum bit de preenchimento ocorre no objeto.
  2. Adicionar apenas uma vez UCHAR_MAX+1 a -1 resultará em um valor no intervalo, a saber UCHAR_MAX

Isso é o suficiente, na verdade! Então, sempre que você quer ter um unsigned char tendo todos os seus bits um, você faz

unsigned char c = (unsigned char)-1;

Segue-se também que uma conversão é não apenas truncando bits de ordem superior. O evento afortunado para complemento de dois é que é apenas um truncamento lá, mas o mesmo não é necessariamente verdade para outras representações de sinais.

35
Johannes Schaub - litb

Como por exemplo, usos de nsigned char:

nsigned 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 um nsigned char. Como os valores de nsigned char caem no intervalo [0,255], os valores são geralmente interpretados como:

  • 0 significando uma falta total de um determinado componente de cor.
  • 255 significando 100% de um determinado pigmento de cor.

Então você acabaria com RGB vermelho como (255,0,0) -> (100% vermelho, 0% verde, 0% azul).

Por que não usar um caractere assinado? A aritmética e a mudança de bit tornam-se problemáticas. Como já explicado, um intervalo de caractere assinado é essencialmente deslocado por -128. Um método muito simples e ingênuo (principalmente não utilizado) para converter RGB em tons de cinza é calcular a média de todos os três componentes de cor, mas isso gera problemas quando os valores dos componentes de cor são negativos. Vermelho (255, 0, 0) calcula a média para (85, 85, 85) ao usar nsigned char aritmética. No entanto, se os valores forem char assinado s (127, -128, -128), acabaríamos com (-99, -99, -99), o que seria (29, 29, 29) no nosso espaço nsigned char, que está incorreto.

24
Zachary Garrett

Se você quiser usar um caractere como um inteiro pequeno, a maneira mais segura de fazer isso é com os tipos int8_tand uint8_t.

12
jbleners

signed char tem faixa 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 sequências de estilo C, use apenas char. Se você precisar usar chars para aritmética (muito raro), especifique assinado ou não assinado explicitamente para portabilidade.

5
James Hopkin

char e unsigned char não são garantidos como tipos de 8 bits em todas as plataformas - eles têm garantia de 8 bits ou mais. Algumas plataformas possuem bytes de 9 bits, 32 bits ou 64 bits . No entanto, as plataformas mais comuns hoje em dia (Windows, Mac, Linux x86, etc.) têm bytes de 8 bits.

5
bk1e

Em termos de valores diretos, um caractere regular é usado quando os valores são conhecidos como CHAR_MIN e CHAR_MAX, enquanto um caractere unsigned fornece o dobro do intervalo no lado positivo. Por exemplo, se CHAR_BIT for 8, o intervalo de char regular só é garantido como [0, 127] (porque pode ser assinado ou não assinado) enquanto unsigned char será [0, 255] e signed char será [-127, 127 ].

Em termos do que é usado, os padrões permitem que objetos de POD (plain old data) sejam convertidos diretamente em um array de char não assinado. Isso permite examinar a representação e os padrões de bits do objeto. A mesma garantia de punting tipo seguro não existe para char ou char assinado.

4
Julienne Walker

unsigned char aceita apenas valores positivos .... like to 255

enquanto que

signed char aceita valores positivos e negativos .... like - 128 to + 127

4
munna

Um caracter não assinado é um valor de byte (não assinado) (0 a 255). Você pode estar pensando em "char" em termos de ser um "personagem", mas é realmente um valor numérico. O "char" regular é assinado, portanto, 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.

3
Zac Gochenour

Se você gosta de usar vários tipos de comprimento e assinatura específicos, provavelmente é melhor usar uint8_t, int8_t, uint16_t, etc, simplesmente porque eles fazem exatamente o que eles dizem.

2
Dark Shikari

Um caractere não assinado usa o bit que é 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].

Caracteres geralmente não assinados são usados ​​quando você não quer um sinal. Isso fará diferença ao fazer coisas como deslocamento de bits (shift estende o sinal) e outras coisas ao lidar com um caractere como um byte em vez de usá-lo como um número.

2
JasonOfEarth

char não assinado é o coração de todo truque de bits. Em quase todos os compiladores para a plataforma ALL, um caractere não assinado é simplesmente um BYTE. Um inteiro sem sinal de (normalmente) 8 bits. que pode ser tratado como um inteiro pequeno ou um pacote de bits.

Além disso, como alguém disse, o padrão não define o sinal de um char. então você tem 3 tipos distintos de "char": char, signed char, unsigned char.

2
ugasoft

Alguns googling encontrados this , onde as pessoas tiveram uma discussão sobre isso.

Um caracter não assinado é basicamente um único byte. Então, você usaria isso se você precisar de um byte de dados (por exemplo, talvez você queira usá-lo para configurar os sinalizadores on e off para serem passados ​​para uma função, como geralmente é feito na API do Windows).

1
dbrien

o caractere unsigned usa somente valores positivos: 0 a 255 caracteres assinados recebem valores positivos e negativos: -128 a +127

0
NL628

citado frome "o livro de programação c":

O qualificador signed ou unsigned pode ser aplicado a char ou a qualquer inteiro. números não assinados são sempre positivos ou nulos, e obedecem às leis do módulo aritmético 2 ^ n, onde n é o número de bits no tipo. Portanto, por exemplo, se chars são 8 bits, variáveis ​​char não assinadas têm valores entre 0 e 255, enquanto chars 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 assinados é máquina -dependente, mas os caracteres imprimíveis são sempre positivos.

0
ZhaoGang