O que significa para um char para ser assinado?

votos
17

Dado que ints assinados e não assinados usar os mesmos registros, etc., e apenas interpretar padrões de bits diferente, e caracteres C são, basicamente, apenas inteiros de 8 bits, o que é a diferença entre caracteres assinados e não assinados em C? Eu entendo que a sinalização de char é definido pela implementação, e eu simplesmente não consigo entender como isso poderia fazer a diferença, pelo menos quando char é usado para segurar cordas em vez de fazer matemática.

Publicado 16/01/2009 em 19:01
fonte usuário
Em outras línguas...                            


9 respostas

votos
21

Ele não vai fazer a diferença para strings. Mas, em C você pode usar um char para fazer contas, quando se vai fazer a diferença.

Na verdade, quando se trabalha em ambientes de memória restrita, como aplicações embarcadas 8 bits um char, muitas vezes, ser usado para fazer matemática, e então ele faz uma grande diferença. Isso ocorre porque não há nenhum bytetipo por padrão no C.

Respondeu 16/01/2009 em 19:06
fonte usuário

votos
17

Em termos dos valores que eles representam:

caracter não identifcado:

  • abrange o intervalo de valores 0..255 (00000000..11111111)
  • valores transbordar borda em torno partir de:

    0 - 1 = 255 (00000000 - 00000001 = 11111111)

  • valores transbordar borda em torno alta como:

    255 + 1 = 0 (11111111 + 00000001 = 00000000)

  • bit a bit operador de deslocamento para a direita ( >>) faz uma mudança lógica:

    10000000 >> 1 = 01000000 (128 / 2 = 64)

signed char:

  • abrange o intervalo de valores -128..127 (10000000..01111111)
  • valores transbordar borda em torno partir de:

    -128 - 1 = 127 (10000000 - 00000001 = 01111111)

  • valores transbordar borda em torno alta como:

    127 + 1 = -128 (01111111 + 00000001 = 10000000)

  • bit a bit operador de deslocamento para a direita ( >>) faz um deslocamento aritmético:

    10000000 >> 1 = 11000000 (-128 / 2 = -64)

Eu incluí as representações binárias para mostrar que o comportamento valor de disposição é puro, aritmética binária consistente e não tem nada a ver com um char a ser assinado / sem assinatura (esperar para mudanças direita).

Atualizar

Alguns comportamentos específicos de aplicação mencionado nos comentários:

Respondeu 16/01/2009 em 20:22
fonte usuário

votos
10
#include <stdio.h>

int main(int argc, char** argv)
{
    char a = 'A';
    char b = 0xFF;
    signed char sa = 'A';
    signed char sb = 0xFF;
    unsigned char ua = 'A';
    unsigned char ub = 0xFF;
    printf("a > b: %s\n", a > b ? "true" : "false");
    printf("sa > sb: %s\n", sa > sb ? "true" : "false");
    printf("ua > ub: %s\n", ua > ub ? "true" : "false");
    return 0;
}


[root]# ./a.out
a > b: true
sa > sb: true
ua > ub: false

É importante ao classificar strings.

Respondeu 16/01/2009 em 19:05
fonte usuário

votos
3

Há um par de diferença. Mais importante, se você estourar o intervalo válido de um char, atribuindo-lhe um número inteiro muito grande ou pequeno, e char é assinado, o valor resultante é definido pela implementação ou mesmo algum sinal (em C) poderia ser aumentado, como para todos os tipos assinados . Contraste isso com o caso quando você atribui alguma coisa demasiado grande ou pequeno para um unsigned char: o valor envolve, você vai ficar semântica precisamente definido. Por exemplo, a atribuição de um -1 a um unsigned char, você receberá um UCHAR_MAX. Assim, sempre que você tem um byte como em um número de 0 a 2 ^ CHAR_BIT, você deve realmente usar unsigned char para armazená-lo.

O sinal também faz a diferença quando se passa para funções vararg:

char c = getSomeCharacter(); // returns 0..255
printf("%d\n", c);

Suponha que o valor atribuído a c seria grande demais para char para representar, e a máquina usa complemento de dois. Muitos se comportam de implementação para o caso que você atribuir um muito grande valor para a char, em que o bit-padrão não vai mudar. Se um int será capaz de representar todos os valores de char (que é para a maioria das implementações), então o caractere está sendo promovido para int antes de passar para printf. Assim, o valor do que é passado seria negativo. Promover para int manteria esse sinal. Então você vai ter um resultado negativo. No entanto, se não assinado char é, em seguida, o valor é sem sinal, e promoção a um int irá produzir um int positivo. Você pode usar unsigned char, comportamento, então você vai se precisamente definido, tanto para a atribuição para a variável, e passando para printf que irá imprimir algo positivo.

Note-se que um char, não assinado e assinado caractere todos são pelo menos 8 bits de largura. Não há exigência de que char é exatamente 8 bits de largura. No entanto, para a maioria dos sistemas que é verdade, mas para alguns, você vai descobrir que eles usam caracteres de 32 bits. Um byte em C e C ++ é definido para ter o tamanho do carvão animal, de modo que um byte em C também nem sempre é exactamente 8 bits.

Outra diferença é que, em C, um char não assinado não deve ter bits de preenchimento. Isto é, se você encontrar CHAR_BIT é 8, então os valores de um unsigned char deve variar entre 0 .. 2 ^ CHAR_BIT-1. O mesmo é verdadeiro para o caractere se for assinado. Para caractere assinado, você não pode assumir qualquer coisa sobre o intervalo de valores, mesmo se você sabe como seu compilador implementa o material sinal (complemento de dois ou as outras opções), pode haver padding bits não utilizados na mesma. Em C ++, não há padding bits para todos os três tipos de caracteres.

Respondeu 16/01/2009 em 19:34
fonte usuário

votos
2

"O que significa para um char para ser assinado?"

Tradicionalmente, o conjunto de caracteres ASCII consiste de codificação de caracteres de 7 bits. (Em contraste com o bit EBCIDIC 8).

Quando a linguagem C foi concebido e implementado este era um problema significativo. (Por várias razões, como transmissão de dados através de dispositivos de modem de série.) O bit extra tem usos como paridade.

A "caráter assinado" passa a ser perfeito para esta representação.

dados binários, OTOH, é simplesmente tomar o valor de cada "pedaço" de 8 bits de dados, portanto, não é necessário nenhum sinal.

Respondeu 16/01/2009 em 20:22
fonte usuário

votos
1

Signedness funciona praticamente da mesma forma em chars como faz em outros tipos integrais. Como você observou, caracteres são realmente apenas números inteiros de um byte. ( Não necessariamente 8-bit !, Embora Há uma diferença, um byte pode ser maior do que 8 bits em algumas plataformas, e chars são bastante ligada à bytes devido às definições de chare sizeof(char)A. CHAR_BITMacro, definidos na <limits.h>ou C ++ 's <climits>, irá dizer-lhe quantos bits estão em um char.).

Quanto à razão que você iria querer um personagem com um sinal: em C e C ++, não há nenhum tipo padrão chamado byte. Para o compilador, chars são bytes e vice-versa, e que não faz distinção entre eles. Às vezes, porém, você quer - às vezes você deseja que charseja um número de um byte, e nesses casos (particularmente o quão pequeno um intervalo de um byte pode ter), você também normalmente importam se o número for assinado ou não. Eu usei pessoalmente signedness (ou unsignedness) para dizer que uma determinada charé um (numérico) "byte" em vez de um personagem, e que ele vai ser usado numericamente. Sem um signedness especificado, que charrealmente é um personagem, e se destina a ser utilizado como texto.

Eu costumava fazer isso, em vez. Agora, as versões mais recentes de C e C ++ têm (u?)int_least8_t(atualmente typedef em <stdint.h>ou <cstdint>), que são mais explicitamente numérico (embora eles vão tipicamente ser apenas typedefs para assinados e não assinados chartipos de qualquer maneira).

Respondeu 16/04/2013 em 18:33
fonte usuário

votos
1

Aritmética em bytes é importante para a computação gráfica (onde os valores de 8 bits são frequentemente utilizados para armazenar cores). Afora isso, eu posso pensar em dois casos principais em que as questões sinal de char:

  • a conversão para um int maior
  • funções de comparação

A coisa desagradável é, estes não irá mordê-lo se todos os seus dados de cadeia é de 7 bits. No entanto, ele promete ser uma fonte inesgotável de bugs obscuros, se você está tentando fazer o seu C / C ++ programa de 8-bit limpo.

Respondeu 16/01/2009 em 20:51
fonte usuário

votos
0

Uma coisa sobre caracteres assinados é que você pode testar c> = '' (espaço) e ter certeza que é um char ascii impressão normal. Claro, não é portátil, assim não é muito útil.

Respondeu 16/01/2009 em 19:39
fonte usuário

votos
0

A única situação que eu posso imaginar este ser um problema é se você optar por fazer matemática em caracteres. É perfeitamente legal para escrever o seguinte código.

char a = (char)42;
char b = (char)120;
char c = a + b;

Dependendo da sinalização do carvão animal, c pode ser um de dois valores. Se o CHAR do são sem sinal, em seguida, c será (char) 162. Se eles são assinados, então ele irá um caso de estouro como o valor máximo para um char assinado é 128. Eu estou supondo que a maioria das implementações seria apenas retornar (char) -32.

Respondeu 16/01/2009 em 19:05
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more