¿Cuál es la diferencia entre int firmado y sin firmar?
c
unsigned-integer
signed-integer
Moumita Das
fuente
fuente
Respuestas:
Como probablemente sepa, los correos
int
electrónicos se almacenan internamente en binario. Normalmente, unaint
contiene 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 int
o ununsigned int
. Con anunsigned 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 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
... 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 int
s el bit más significativo es1
si y solo si el número es negativo. Por eso, parasigned int
s, este bit se conoce como "bit de signo".fuente
(unsigned)(-1)
se requiere que sea el valor máximo representable paraunsigned
(independiente de la representación binaria), lo cual es trivialmente cierto para el complemento a dos, pero no para otras representaciones.int
yunsigned int
son dos tipos de enteros distintos. (int
también puede denominarsesigned int
, o simplementesigned
;unsigned int
también puede denominarseunsigned
.)Como los nombres implican,
int
es un firmado tipo entero, yunsigned int
es un unsigned tipo entero. Eso significa queint
puede representar valores negativos yunsigned int
solo puede representar valores no negativos.El lenguaje C impone algunos requisitos a los rangos de estos tipos. La gama de
int
debe ser al menos-32767
..+32767
, y la gama deunsigned int
debe ser al menos0
..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.int
normalmente 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. Porqueunsigned int
no hay desbordamiento; cualquier operación que arroje un valor fuera del rango del tipo se envuelve, por ejemploUINT_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_MIN
yINT_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 siempre
i
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 ).i
i--
UINT_MAX
fuente
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.fuente
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.
fuente
En la práctica, existen dos diferencias:
cout
en C ++ oprintf
en C): la representación de bits enteros sin signo se interpreta como un entero no negativo por las funciones de impresión.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");
fuente