GNU/Linux >> Tutoriales Linux >  >> Linux

Tutorial de programación de Linux C Parte 15 - Números negativos y complemento 2s

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.


Linux
  1. Tutorial de comandos agradable y renice de Linux (7 ejemplos)

  2. Tutorial de Programación en C Parte 5 - Variables de carácter

  3. Tutorial de programación de Linux C Parte 10 - Ámbitos variables

  4. Tutorial de programación de Linux C Parte 9:Cadenas

  5. Tutorial de programación de Linux C, parte 8:llamada por valor frente a llamada por puntero/dirección

5 consejos y trucos interesantes sobre la línea de comandos en Linux – Parte 1

Cómo comparar números y cadenas en Linux Shell Script

Cómo comparar y fusionar archivos de texto en Linux (parte 2)

Tutorial de programación de Linux C Parte 18:funciones recursivas

Cómo instalar y usar KompoZer en Linux - Tutorial

Discusión sobre Windows, Linux y cPanel VPS – Parte II