Saltar al contenido

(-2147483648> 0) devuelve true en C++?

Nuestros mejores programadores han agotado sus reservas de café, en su búsqueda todo el tiempo por la solución, hasta que Gustavo encontró la contestación en Bitbucket y hoy la compartimos contigo.

Solución:

-2147483648 no es un “número”. El lenguaje C++ no admite valores literales negativos.

-2147483648 es en realidad una expresión: un valor literal positivo 2147483648 con unario - operador frente a él. Valor 2147483648 es aparentemente demasiado grande para el lado positivo de int gama en su plataforma. Si escribe long int tuviera un mayor rango en su plataforma, el compilador tendría que asumir automáticamente que 2147483648 posee long int tipo. (En C++11 el compilador también tendría que considerar long long int type.) Esto haría que el compilador evalúe -2147483648 en el dominio de tipo más grande y el resultado sería negativo, como era de esperar.

Sin embargo, aparentemente en su caso el rango de long int es el mismo que el rango de inty en general no hay ningún tipo entero con mayor rango que int en tu plataforma. Esto significa formalmente que la constante positiva 2147483648 desborda todos los tipos de enteros con signo disponibles, lo que a su vez significa que el comportamiento de su programa no está definido. (Es un poco extraño que la especificación del idioma opte por un comportamiento indefinido en tales casos, en lugar de requerir un mensaje de diagnóstico, pero así son las cosas).

En la práctica, teniendo en cuenta que el comportamiento es indefinido, 2147483648 podría interpretarse como un valor negativo dependiente de la implementación que se vuelve positivo después de tener unario - aplicado a ella. Alternativamente, algunas implementaciones podrían decidir intentar usar tipos sin firmar para representar el valor (por ejemplo, en C89/90 los compiladores debían usar unsigned long int, pero no en C99 o C++). Las implementaciones pueden hacer cualquier cosa, ya que el comportamiento no está definido de todos modos.

Como nota al margen, esta es la razón por la cual constantes como INT_MIN normalmente se definen como

#define INT_MIN (-2147483647 - 1)

en lugar de lo aparentemente más sencillo

#define INT_MIN -2147483648

Este último no funcionaría según lo previsto.

El compilador (VC2012) promociona a los enteros “mínimos” que pueden contener los valores. En el primer caso, signed int (y long int) no puede (antes de que se aplique el signo), pero unsigned int puede: 2147483648 posee unsigned int ???? tipo. En el segundo obligas int desde el unsigned.

const bool i= (-2147483648 > 0) ;  //   --> true

advertencia C4146: operador menos unario aplicado a tipo sin firmarresultado todavía no firmado

Aquí hay “curiosidades” relacionadas:

const bool b= (-2147483647      > 0) ; //  false
const bool i= (-2147483648      > 0) ; //  true : result still unsigned
const bool c= ( INT_MIN-1       > 0) ; //  true :'-' int constant overflow
const bool f= ( 2147483647      > 0) ; //  true
const bool g= ( 2147483648      > 0) ; //  true
const bool d= ( INT_MAX+1       > 0) ; //  false:'+' int constant overflow
const bool j= ( int(-2147483648)> 0) ; //  false : 
const bool h= ( int(2147483648) > 0) ; //  false
const bool m= (-2147483648L     > 0) ; //  true 
const bool o= (-2147483648LL    > 0) ; //  false

Estándar C++11:

2.14.2 Literales enteros [lex.icon]

Un literal entero es una secuencia de dígitos que no tiene punto ni exponente. Un literal entero puede tener un prefix que especifica su base y un sufijo que especifica su tipo.

El tipo de un literal entero es el primero de la lista correspondiente en la que se puede representar su valor.

ingrese la descripción de la imagen aquí

Si un literal entero no puede ser representado por ningún tipo en su lista y un tipo entero extendido (3.9.1) puede representar su valor, puede tener ese tipo entero extendido. Si todos los tipos de la lista del literal están firmados, se firmará el tipo entero extendido. Si todos los tipos de la lista del literal no tienen signo, el tipo entero extendido no tendrá signo. Si la lista contiene tipos con y sin signo, el tipo entero extendido puede ser con o sin signo. Un programa está mal formado si una de sus unidades de traducción contiene un literal entero que no puede ser representado por ninguno de los tipos permitidos.

Y estas son las reglas de promoción para números enteros en el estándar.

4.5 Promociones Integrales [conv.prom]

Un valor pr de un tipo entero distinto de bool, char16_t, char32_to
wchar_t cuyo rango de conversión de enteros (4.13) es menor que el rango de int se puede convertir a un prvalue de tipo int Si int puede representar todos los valores del tipo fuente; de lo contrario, el prvalue de origen se puede convertir en un prvalue de tipo unsigned int.

En breve, 2147483648 se desborda a -2147483648y (-(-2147483648) > 0) es true.

Así es como 2147483648 parece en binario.

Además, en el caso de cálculos binarios con signo, el bit más significativo (“MSB”) es el bit de signo. Esta pregunta puede ayudar a explicar por qué.

Puedes asentar nuestra faena mostrando un comentario y valorándolo te damos las gracias.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *