¿Qué sucede cuando asigno un valor negativo a un int sin signo? [duplicate]

5 minutos de lectura

avatar de usuario
n0nchun

Posible duplicado:

Conversión firmada a no firmada en C: ¿siempre es seguro?

Digamos que declaro una variable de tipo int sin firmar: unsigned int x = -1;

Ahora, el complemento de -1 en dos (suponiendo una máquina de 32 bits) es 0xFFFFFFFF. Ahora, cuando asigné este valor a x, ¿se asignó el valor 0x7FFFFFFF a x?

Si fuera así, entonces printf (“%d”,x); habría impreso el equivalente decimal de 0x7FFFFFFF, ¿verdad? Pero, claramente, esto no está sucediendo, ya que el valor que se imprime es -1. ¿Que me estoy perdiendo aqui?

Editar: sé que podemos usar el especificador de formato% u para imprimir valores sin firmar. Pero eso no ayuda a responder la pregunta anterior.

  • donde fue 0x7FFFFFFF ¿viene de?

    -Evan Mulawski

    22 de agosto de 2011 a las 19:48

  • @Evan: Volteando el MSB. Solo una suposición, ya que no sé cómo ocurre realmente la conversión.

    – n0n Chun

    22 de agosto de 2011 a las 19:59

  • La sección 6.3.1.3 del estándar C99 debería responder a su pregunta. Pero esto debería responder a su pregunta un poco mejor stackoverflow.com/questions/50605/…

    – José

    22 de agosto de 2011 a las 20:16

avatar de usuario
keith thompson

los "%d" el formato es para valores int (con signo). Si lo usa con un valor sin firmar, podría imprimir algo diferente al valor real. Utilizar "%u" para ver el valor real, o %x para verlo en hexadecimal.

en la declaracion

unsigned int x = -1;

la expresion -1 es de tipo int y tiene el valor -1. El inicializador convierte este valor de int a int sin signo. Las reglas para la conversión de firmado a sin firmar dicen que el valor se reduce módulo UINT_MAX + 1entonces -1 se convertirá en UINT_MAX (que es probablemente 0xffffffff o 4294967295 si unsigned int es de 32 bits).

Tu simplemente no poder asignar un valor negativo a un objeto de un tipo sin signo. Cualquier valor de este tipo se convertirá al tipo sin firmar antes de que se asigne, y el resultado siempre será >= 0.

  • Pero Keith, entonces, 0x FF FF FF FF tiene MSB 1, que se usa para denotar números negativos, ¿verdad? Entonces, ¿qué hemos ganado realmente al asignar un valor negativo a una variable de tipo int sin signo?

    – n0n Chun

    22 de agosto de 2011 a las 20:03

  • @n0nChun: Esa no es la única forma en que se pueden representar los números negativos. El complemento a 2 es el método más común; otros son complemento a 1 y signo y magnitud (los tres están permitidos por el estándar C). Y el punto es que literalmente no poder asignar un valor negativo a un int sin signo; cualquier valor negativo se convertirá implícitamente, dando como resultado un valor sin signo no negativo. Es más, unsigned int no es necesariamente de 32 bits; puede ser tan pequeño como 16 bits. -1 siempre se convertirá en UINT_MAXque no es necesariamente 0xffffffff.

    –Keith Thompson

    22 de agosto de 2011 a las 20:30

  • @n0nChun, el MSB no se usa para indicar números negativos en enteros sin signo. si utiliza %u, verá 2 * 0x7fffffff. El máximo para entradas sin firmar es 2 veces mayor.

    – Daniel

    22 de agosto de 2011 a las 20:34

  • @Daniel: 2 veces más grande más 1.

    –Keith Thompson

    22 de agosto de 2011 a las 20:52

  • @keith Gracias por la corrección. Como no hay necesidad de +/- 0, hay un número negativo más que un número positivo. Cada número negativo se asigna a un número sin signo, de ahí viene el +1.

    – Daniel

    22 de agosto de 2011 a las 21:51

Utilizar %u en lugar de %d para imprimir valores sin firmar. Entonces debería ver 0xFFFFFFFF.

  • lo se pero no responde mi pregunta

    – n0n Chun

    22 de agosto de 2011 a las 19:54

  • Asignar -1 a un int sin firmar no solo elimina el bit de signo (0x7FF…) seguirá siendo 0xFF…, use esto printf("%1$u : 0x%1$X\n", x); para ver por ti mismo.

    – José

    22 de agosto de 2011 a las 19:57


  • x = -1 y x = 0xFFFFFFFF debe dar lo mismo. x = 0x7FFFFFFF es un valor diferente y no lo obtendrá de ninguna de las asignaciones anteriores. Si esto todavía no lo aclara, entonces no estoy seguro de qué más estás preguntando…

    –Eran Zimmerman Gonen

    22 de agosto de 2011 a las 19:59

  • Olvídese de que tiene un int sin firmar y piense en él como un espacio en la memoria. Cuando asignó su variable a -1, lo que realmente está diciendo es almacenar el valor del int con signo -1 en este espacio en la memoria. Luego, con printf, %d le pide que lea un int firmado desde ese espacio en la memoria. Ambos son consistentes, por lo que obtendrá un -1. Su espacio en la memoria podría ser una variable de cualquier tipo y aún verá “-1”.

    – asc99c

    22 de agosto de 2011 a las 20:15


  • @ asc99c: si bien su explicación de printf ‘% d’ es correcta, su asignación no lo es. La especificación C99 en realidad especifica el comportamiento para esto, no es solo una simple asignación de memoria. 2) De lo contrario, si el nuevo tipo no tiene signo, el valor se convierte sumando o restando repetidamente uno más que el valor máximo que se puede representar en el nuevo tipo hasta que el valor esté en el rango del nuevo tipo.

    – José

    22 de agosto de 2011 a las 20:28

Lo que sucede es que primero convierte el valor a int sin firmar, asignando 0xffffffff a x. Luego, usando printf(“%d\n”), volverá a convertir el valor a int firmado y conservará el valor de 0xffffffff. Así imprimiendo -1.

  • Cerca, pero no del todo. Él convierteno yesos el valor (la conversión es implícita, no se realiza a través de un operador de conversión). Y el printf la llamada no realiza una conversión de tipo; más bien, probablemente interpreta la representación del valor sin signo como si fuera un valor con signo (juego de palabras). (Estrictamente hablando, el comportamiento de los printf la llamada no está definida).

    –Keith Thompson

    22 de agosto de 2011 a las 19:56

  • Sí, tienes razón, estoy usando la palabra incorrecta. Si observa la salida de asm de gcc, se mostrarán dos mov, lo que dará como resultado una interpretación justa del valor.

    – Rickard

    22 de agosto de 2011 a las 19:57

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad