Hasta ahora, en esta serie de tutoriales de programación en C en curso, hemos discutido bastantes conceptos, pero nos hemos perdido uno básico. Se trata de números negativos. Sí, aunque mencionamos brevemente las variables con signo y sin signo en uno de nuestros tutoriales iniciales, en realidad no discutimos cómo se almacenan los números negativos en la memoria.
Bueno, eso es exactamente lo que se discutirá en este tutorial. Entonces, sin más preámbulos, comencemos con la discusión.
complemento a 2
Antes de comenzar con la explicación sobre la representación de números negativos en la memoria, es importante que conozcamos el concepto de complemento a 1 y complemento a 2, los cuales son operaciones de nivel binario.
Tomemos un ejemplo muy simple. Suponga que tiene un entero de 4 bytes 'a' con valor decimal 15. Entonces, así es como se representa en la memoria de forma binaria:
00000000 00000000 00000000 00001111
Ahora, para calcular el complemento a uno, simplemente invierta todos los bits. Así que la siguiente es la representación en complemento a 1 de 15:
11111111 11111111 11111111 11110000
Ahora, si sumas 1 a la representación binaria anterior, obtienes el complemento a 2.
11111111 11111111 11111111 11110001
Así que la representación anterior es el complemento a dos de 15.
Números negativos
Ahora, algunos de ustedes deben estar pensando por qué discutimos el complemento de 1 y 2. Bueno, la respuesta está en que la representación binaria de un número negativo se calcula a través del complemento a 2.
¿Difícil de creer? Aquí está la prueba:
El complemento a 2 que calculamos en la sección anterior se puede representar en forma hexadecimal como 0xFFFFFFF1. Ahora, veamos cuál es este valor en forma decimal a través de un programa C
Aquí está el código:
#include <stdio.h>
int main()
{
int a = 0xFFFFFFF1;
printf("a = %d", a);
return 0;
}
Y la siguiente es la salida:
a = -15
¿Creerlo ahora? Comenzamos con un número '15', calculamos su complemento a 2, y cuando volvimos a convertir el valor del complemento a dos en decimal, encontramos que es -15.
Continuando, ahora modifiquemos ligeramente el código para asegurarnos de que la llamada printf lea el valor de la variable 'a' -gr-id="60">como un entero sin signo.
#include <stdio.h>
int main()
{
int a = 0xFFFFFFF1;
printf("a = %u", a);
return 0;
}
Aquí está la salida ahora:
a = 4294967281
Ups, la salida cambió, y ahora es un gran valor positivo. Pero ¿por qué sucedió esto? ¿No es 0xFFFFFFF1 el complemento a 2 de 15 como vimos antes?
Sí, 0xFFFFFFF1 es el complemento a dos de 15, pero si no lo miras desde esa perspectiva, también es un valor normal (4294967281). La diferencia radica en cómo se lee. Si se lee como un entero con signo (a través de %d en printf), verá el resultado como -15, pero si se lee como un entero sin signo (a través de %u en printf), verá el resultado como 4294967281.
Como regla general, con las variables con signo (que manejan valores tanto negativos como positivos), tenga en cuenta que la representación binaria de números negativos siempre tiene '1' como el bit más a la izquierda, mientras que en el caso de números positivos, el bit en cuestión siempre es 0.
Finalmente, tenga en cuenta que también puede invertir la representación del complemento a dos para obtener su contraparte positiva. Como ejemplo, tomemos de nuevo el valor 0xFFFFFFF1, que es la representación hexadecimal de -15. Se representa en forma binaria como:
11111111 11111111 11111111 11110001
Ahora, para obtener su contraparte positiva, solo realiza un complemento a 2 nuevamente. Lo que significa, primero haz un complemento a 1:
00000000 00000000 00000000 00001110
Y luego agrega 1
00000000 00000000 00000000 00001111
Ahora, si conviertes esto, obtendrás el valor 15 en forma decimal.
Conclusión
Espero que este tutorial te haya ayudado a comprender el concepto de números negativos en el contexto de cómo se representan en la memoria. Le sugiero que pruebe los ejemplos que usamos en este tutorial, y en caso de que encuentre algún problema, o si tiene alguna duda o consulta, envíenos un comentario a continuación.