Qual é a diferença entre assinado e não assinado int?
c
unsigned-integer
signed-integer
Moumita Das
fonte
fonte
Respostas:
Como você provavelmente sabe, os
int
s são armazenados internamente em binário. Normalmente, umint
contém 32 bits, mas em alguns ambientes pode conter 16 ou 64 bits (ou até mesmo um número diferente, geralmente, mas não necessariamente, uma potência de dois).Mas para este exemplo, vamos olhar para inteiros de 4 bits. Minúsculo, mas útil para fins ilustrativos.
Como há quatro bits nesse número inteiro, ele pode assumir um de 16 valores; 16 é dois à quarta potência, ou 2 vezes 2 vezes 2 vezes 2. Quais são esses valores? A resposta depende se este inteiro é a
signed int
ou anunsigned int
. Com umunsigned int
, o valor nunca é negativo; não há nenhum sinal associado ao valor. Aqui estão os 16 valores possíveis de um quatro bitsunsigned int
:bits value 0000 0 0001 1 0010 2 0011 3 0100 4 0101 5 0110 6 0111 7 1000 8 1001 9 1010 10 1011 11 1100 12 1101 13 1110 14 1111 15
... e aqui estão os 16 valores possíveis de um quatro bits
signed int
:bits value 0000 0 0001 1 0010 2 0011 3 0100 4 0101 5 0110 6 0111 7 1000 -8 1001 -7 1010 -6 1011 -5 1100 -4 1101 -3 1110 -2 1111 -1
Como você pode ver, para
signed int
s o bit mais significativo é1
se e somente se o número for negativo. É por isso que, parasigned int
s, esse bit é conhecido como "bit de sinal".fonte
(unsigned)(-1)
é necessário que seja o valor máximo representável paraunsigned
(independente da representação binária), o que é trivialmente verdadeiro para o complemento de 2, mas não para outras representações.int
eunsigned int
são dois tipos inteiros distintos. (int
também pode ser referido comosigned int
, ou apenassigned
;unsigned int
também pode ser referido comounsigned
.)Como o nome implica,
int
é um assinado tipo inteiro, eunsigned int
é um sem assinatura tipo inteiro. Isso significa queint
é capaz de representar valores negativos eunsigned int
pode representar apenas valores não negativos.A linguagem C impõe alguns requisitos aos intervalos desses tipos. A faixa de
int
tem de ser, pelo menos,-32767
..+32767
, e o intervalo deunsigned int
tem de ser, pelo menos,0
..65535
. Isso significa que ambos os tipos devem ter pelo menos 16 bits. Eles têm 32 bits em muitos sistemas, ou mesmo 64 bits em alguns.int
normalmente tem um valor negativo extra devido à representação de complemento de dois usada pela maioria dos sistemas modernos.Talvez a diferença mais importante seja o comportamento da aritmética com sinal vs. sem sinal. Para assinados
int
, o estouro tem comportamento indefinido. Poisunsigned int
, não há transbordamento; qualquer operação que produza um valor fora do intervalo do tipo envolve, por exemploUINT_MAX + 1U == 0U
.Qualquer tipo de inteiro, com ou sem sinal, modela uma subfaixa do conjunto infinito de inteiros matemáticos. Desde que você trabalhe com valores dentro da faixa de um tipo, tudo funciona. Ao se aproximar do limite inferior ou superior de um tipo, você encontra uma descontinuidade e pode obter resultados inesperados. Para tipos inteiros com sinal, os problemas ocorrem apenas para valores negativos e positivos muito grandes, excedendo
INT_MIN
eINT_MAX
. Para tipos inteiros sem sinal, ocorrem problemas para valores positivos muito grandes e em zero . Isso pode ser uma fonte de bugs. Por exemplo, este é um loop infinito:for (unsigned int i = 10; i >= 0; i --) [ printf("%u\n", i); }
porque
i
é sempre maior ou igual a zero; essa é a natureza dos tipos sem sinal. (Dentro do loop, quandoi
é zero,i--
define seu valor comoUINT_MAX
.)fonte
Às vezes sabemos de antemão que o valor armazenado em uma determinada variável inteira será sempre positivo - quando está sendo usado apenas para contar coisas, por exemplo. Nesse caso, podemos declarar a variável sem sinal, como em
unsigned int num student;
,. Com tal declaração, o intervalo de valores inteiros permitidos (para um compilador de 32 bits) mudará do intervalo -2147483648 a +2147483647 para o intervalo 0 a 4294967295. Assim, declarar um número inteiro como não assinado quase duplica o tamanho do maior possível valor que ele pode conter.fonte
Em termos leigos, um int sem sinal é um número inteiro que não pode ser negativo e, portanto, tem um intervalo maior de valores positivos que pode assumir. Um int com sinal é um inteiro que pode ser negativo, mas tem um intervalo positivo inferior em troca de valores mais negativos que pode assumir.
fonte
Na prática, existem duas diferenças:
cout
em C ++ ouprintf
em C): a representação do bit inteiro sem sinal é interpretada como um inteiro não negativo pelas funções de impressão.este código pode identificar o inteiro usando o critério de pedido:
char a = 0; a--; if (0 < a) printf("unsigned"); else printf("signed");
fonte