Representación de números negativos en C?

¿Cómo C representa números enteros negativos?

¿Es a través de la representación del complemento de dos o usando el MSB (bit más significativo)?

-1 en hexadecimal es ffffffff .

Así que aclaren esto por mí.

ISO C (C99), sección 6.2.6.2/2 , establece que una implementación debe elegir una de tres representaciones diferentes para tipos de datos integrales, complemento de dos, complemento de uno o signo / magnitud (aunque es muy probable que las implementaciones de complemento de dos lejos superan a los demás).

En todas esas representaciones, los números positivos son idénticos, la única diferencia son los números negativos.

Para obtener la representación negativa de un número positivo, usted:

  • invierta todos los bits y luego agregue uno para complemento de dos.
  • invierta todos los bits para el complemento de uno.
  • invierta solo el signo de signo / magnitud.

Puedes ver esto en la tabla a continuación:

 número |  complemento de dos |  complemento de unos |  signo / magnitud
 ======= | ====================== ==================== = | ====================
      5 |  0000 0000 0000 0101 |  0000 0000 0000 0101 |  0000 0000 0000 0101
     -5 |  1111 1111 1111 1011 |  1111 1111 1111 1010 |  1000 0000 0000 0101

Tenga en cuenta que ISO no exige que todos los bits se utilicen en la representación. Introducen el concepto de un bit de signo, bits de valor y bits de relleno. Ahora, en realidad, nunca he visto una implementación con bits de relleno pero, según el documento de justificación C99, tienen esta explicación:

Supongamos que una máquina usa un par de cortos de 16 bits (cada uno con su propio bit de signo) para formar un int de 32 bits y el bit de signo del short inferior se ignora cuando se usa en este int de 32 bits. Entonces, como un int. Firmado de 32 bits, hay un bit de relleno (en el medio de los 32 bits) que se ignora al determinar el valor de la int firmada de 32 bits. Pero, si este elemento de 32 bits se trata como un int sin signo de 32 bits, ese bit de relleno es visible para el progtwig del usuario. Al comité C se le dijo que hay una máquina que funciona de esta manera, y esa es una de las razones por las que se agregaron los bits de relleno a C99.

Creo que la máquina a la que se podían estar refiriendo era la Datacraft 6024 (y sus sucesoras de Harris Corp). En esas máquinas, tenía una palabra de 24 bits utilizada para el entero con signo, pero, si quería el tipo más amplio, ensartaba dos de ellas juntas como un valor de 47 bits con el bit de signo de una de las palabras ignoradas:

 +---------+-----------+--------+-----------+ | sign(1) | value(23) | pad(1) | value(23) | +---------+-----------+--------+-----------+ \____________________/ \___________________/ upper word lower word 

C permite el signo / magnitud, el complemento de uno y las representaciones complementarias de dos de enteros con signo. La mayoría del hardware típico utiliza dos complementos para enteros y signo / magnitud para coma flotante (y otra posibilidad más: una representación de “sesgo” para el exponente de coma flotante).

-1 en hexadecimal es ffffffff. Así que por favor aclarenme a este respecto.

En el complemento a dos (con mucho, la representación más comúnmente utilizada), cada bit excepto el bit más significativo (MSB), de derecha a izquierda (aumentando el orden de magnitud) tiene un valor 2 n donde n aumenta de cero en uno. El MSB tiene el valor -2 n .

Entonces, por ejemplo, en un entero de complemento de dos bits de 8 bits, el MSB tiene el valor de posición -2 7 (-128), por lo que el número binario: 1111 1111 2 es igual a -128 + 0111 1111 2 = -128 + 127 = -1

Una característica útil del complemento de dos es que la ALU de un procesador solo requiere un bloque sumdor para realizar la resta, formando el complemento de dos del operando de la mano derecha. Por ejemplo, 10 – 6 es equivalente a 10 + (-6); en binario de 8 bits (por simplicidad de explicación) esto se ve así:

  0000 1010 +1111 1010 --------- [1]0000 0100 = 4 (decimal) 

Donde el [1] es el bit de acarreo descartado. Otro ejemplo; 10 – 11 == 10 + (-11):

  0000 1010 +1111 0101 --------- 1111 1111 = -1 (decimal) 

Otra característica del complemento de dos es que tiene un valor único que representa cero, mientras que la magnitud de signo y el complemento de uno tienen dos; +0 y -0.

Para los tipos integrales, generalmente es un complemento de dos (específico de la implementación). Para el punto flotante, hay un bit de signo.