¿Cuál es la diferencia entre int firmado y no firmado?

91

¿Cuál es la diferencia entre int firmado y sin firmar?

Moumita Das
fuente
5
Esta es una pregunta real, y la respuesta no es tan simple sino más bien sutil.
R .. GitHub DEJA DE AYUDAR A ICE
Votación para reabrir. Puede ser un duplicado, pero definitivamente es una pregunta real.
Brian
4
Re: "Podría ser un duplicado" - ¿Cuál es la diferencia entre int sin firmar e int firmado en C?
eldarerathis
Deben agregarse más etiquetas, ya que muchos idiomas las usan.
Juan Boero
Esta pregunta puede necesitar un capítulo para desarrollarla. Si desea conocer los entresijos, consulte Enteros firmados y sin firmar para obtener más explicaciones.
anónimo

Respuestas:

113

Como probablemente sepa, los correos intelectrónicos se almacenan internamente en binario. Normalmente, una intcontiene 32 bits, pero en algunos entornos puede contener 16 o 64 bits (o incluso un número diferente, por lo general, pero no necesariamente una potencia de dos).

Pero para este ejemplo, veamos enteros de 4 bits. Diminuto, pero útil con fines ilustrativos.

Como hay cuatro bits en dicho número entero, puede asumir uno de 16 valores; 16 es dos elevado a la cuarta potencia, o 2 por 2 por 2 por 2. ¿Cuáles son esos valores? La respuesta depende de si este entero es un signed into un unsigned int. Con an unsigned int, el valor nunca es negativo; no hay ningún signo asociado con el valor. Aquí están los 16 valores posibles de un cuatro bits unsigned 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

... y aquí están los 16 valores posibles de un cuatro 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 puede ver, para signed ints el bit más significativo es 1si y solo si el número es negativo. Por eso, para signed ints, este bit se conoce como "bit de signo".

Bill Evans en Mariposa
fuente
11
Quizás vale la pena señalar que este es el formato de complemento a dos, que es cierto que hoy en día es muy utilizado. También hay otras formas de representar números enteros con signo, sobre todo el complemento de uno.
Schedler
Correcto. Y el estándar ISO9899 C ni siquiera requiere que se utilice el complemento de uno o el complemento de dos; cualquier otra convención que realmente funcione está permitida.
Bill Evans en Mariposa
1
Aunque no se requiere el complemento a dos, (unsigned)(-1)se requiere que sea el valor máximo representable para unsigned(independiente de la representación binaria), lo cual es trivialmente cierto para el complemento a dos, pero no para otras representaciones.
rubenvb
3
@BillEvansatMariposa: El estándar dice que para enteros con signo hay 3 representaciones permitidas: signo + magnitud, complemento a 2, complemento a 1. Cualquier otro tendría que ser invisible para el programa y ser percibido como uno de estos 3.
Alexey Frunze
Ok, pero bajo el capó! ¡Qué está pasando REALMENTE! ¿Cuál es la diferencia entre un número FIRMADO y NO FIRMADO? ¿Cómo gestiona la máquina el cálculo? ¿Solo resta un valor del otro? ¿Cómo se diferencian 1111 = 15 y 1111 = -1?
Mihail Georgescu
19

inty unsigned intson dos tipos de enteros distintos. ( inttambién puede denominarse signed int, o simplemente signed; unsigned inttambién puede denominarse unsigned.)

Como los nombres implican, intes un firmado tipo entero, y unsigned intes un unsigned tipo entero. Eso significa que intpuede representar valores negativos y unsigned intsolo puede representar valores no negativos.

El lenguaje C impone algunos requisitos a los rangos de estos tipos. La gama de intdebe ser al menos -32767.. +32767, y la gama de unsigned intdebe ser al menos 0.. 65535. Esto implica que ambos tipos deben tener al menos 16 bits. Son de 32 bits en muchos sistemas, o incluso de 64 bits en algunos. intnormalmente tiene un valor negativo adicional debido a la representación en complemento a dos utilizada por la mayoría de los sistemas modernos.

Quizás la diferencia más importante es el comportamiento de la aritmética con signo y sin signo. Para firmado int, el desbordamiento tiene un comportamiento indefinido. Porque unsigned intno hay desbordamiento; cualquier operación que arroje un valor fuera del rango del tipo se envuelve, por ejemplo UINT_MAX + 1U == 0U.

Cualquier tipo de entero, con o sin signo, modela un subrango del conjunto infinito de enteros matemáticos. Siempre que trabaje con valores dentro del rango de un tipo, todo funciona. Cuando se acerca al límite inferior o superior de un tipo, encuentra una discontinuidad y puede obtener resultados inesperados. Para los tipos enteros con signo, los problemas ocurren solo para valores muy grandes negativos y positivos, que exceden INT_MINy INT_MAX. Para los tipos enteros sin signo, se producen problemas para valores positivos muy grandes y en cero . Esto puede ser una fuente de errores. Por ejemplo, este es un bucle infinito:

for (unsigned int i = 10; i >= 0; i --) [
    printf("%u\n", i);
}

porque siemprei es mayor o igual a cero; esa es la naturaleza de los tipos sin firmar. (Dentro del ciclo, cuando es cero, establece su valor en ).ii--UINT_MAX

Keith Thompson
fuente
12

A veces sabemos de antemano que el valor almacenado en una variable entera dada siempre será positivo, cuando se usa solo para contar cosas, por ejemplo. En tal caso se puede declarar la variable no está firmado, como en, unsigned int num student;. Con tal declaración, el rango de valores enteros permitidos (para un compilador de 32 bits) cambiará del rango -2147483648 a +2147483647 al rango 0 a 4294967295. Por lo tanto, declarar un entero como sin signo casi duplica el tamaño del mayor posible valor que de otro modo puede tener.

imran
fuente
@Alex Estaba en medio de la edición de esa respuesta hace 10 minutos y es idéntica. lol
Skuld
12

En términos sencillos, un int sin signo es un número entero que no puede ser negativo y, por lo tanto, tiene un rango más alto de valores positivos que puede asumir. Un int con signo es un número entero que puede ser negativo pero tiene un rango positivo más bajo a cambio de valores más negativos que puede asumir.

usuario2977636
fuente
0

En la práctica, existen dos diferencias:

  1. impresión (por ejemplo, con couten C ++ o printfen C): la representación de bits enteros sin signo se interpreta como un entero no negativo por las funciones de impresión.
  2. pedido : el pedido depende de la especificación firmada o no firmada.

este código puede identificar el número entero usando el criterio de orden:

char a = 0;
a--;
if (0 < a)
    printf("unsigned");
else
    printf("signed");
Minimus Heximus
fuente
Si esto explica la diferencia de que uno se trate de números negativos y el otro, no. Ayudaría mucho a esta publicación.
Daniel Jackson
@DanielJackson No queda claro lo que dices. un char puede considerarse negativo o positivo según el compilador. la salida del código depende de lo que elija el compilador y esto muestra la diferencia entre firmado y no firmado.
Minimus Heximus