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

-2147483648 es el número entero más pequeño para el tipo entero con 32 bits, pero parece que se desbordará en la oración if(...) :

 if (-2147483648 > 0) std::cout << "true"; else std::cout << "false"; 

Esto se imprimirá true en mis pruebas. Sin embargo, si lanzamos -2147483648 a entero, el resultado será diferente:

 if (int(-2147483648) > 0) std::cout << "true"; else std::cout << "false"; 

Esto imprimirá false .

Estoy confundido. ¿Alguien puede dar una explicación sobre esto?


Actualización 02-05-2012:

Gracias por sus comentarios, en mi comstackdor, el tamaño de int es de 4 bytes. Estoy usando VC para algunas pruebas simples. Cambié la descripción en mi pregunta.

Esas son muchas buenas respuestas en este post, AndreyT dio una explicación muy detallada sobre cómo el comstackdor actuará en dicha entrada y cómo se implementó este entero mínimo. qPCR4vir, por otro lado, dio algunas “curiosidades” relacionadas y cómo se representan los números enteros. ¡Tan impresionante!

-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 en frente de él. El valor 2147483648 es aparentemente demasiado grande para el lado positivo del rango int en su plataforma. Si type long int tiene un rango mayor en su plataforma, el comstackdor debería asumir automáticamente que 2147483648 tiene long int tipo long int . (En C ++ 11, el comstackdor también debería considerar el tipo long long int ). Esto haría que el comstackdor evaluara -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 int , y en general no hay ningún tipo de entero con un rango mayor que int en su plataforma. Esto significa formalmente que la constante positiva 2147483648 desborda todos los tipos de entero con signo disponibles, lo que a su vez significa que el comportamiento de su progtwig no está definido. (Es un poco extraño que la especificación del lenguaje 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 no está definido, 2147483648 podría interpretarse como un valor negativo dependiente de la implementación que pasa a ser positivo después de haberlo aplicado unariamente. Alternativamente, algunas implementaciones pueden decidir intentar usar tipos sin signo para representar el valor (por ejemplo, en C89 / 90 los comstackdores deben 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 las constantes como INT_MIN se suelen definir como

 #define INT_MIN (-2147483647 - 1) 

en lugar de la aparentemente más sencilla

 #define INT_MIN -2147483648 

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

El comstackdor (VC2012) promueve los enteros “mínimos” que pueden contener los valores. En el primer caso, signed int (y long int ) no puede (antes de aplicar el signo), pero unsigned int puede: 2147483648 tiene unsigned int ???? tipo. En el segundo forzarás int del unsigned .

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

advertencia C4146: operador unario negativo aplicado al tipo sin signo , resultado aún sin firmar

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 una parte de período o exponente. Un literal entero puede tener un prefijo que especifique su base y un sufijo que especifique su tipo.

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

enter image description here

Si un literal entero no puede ser representado por ningún tipo en su lista y un tipo de entero extendido (3.9.1) puede representar su valor, puede tener ese tipo de entero extendido. Si se firman todos los tipos en la lista para el literal, se firmará el tipo entero extendido. Si todos los tipos en la lista para el literal no están firmados, el tipo entero extendido no tendrá firma. Si la lista contiene tipos firmados y no firmados, el tipo de entero extendido puede estar firmado o no. Un progtwig 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 enteros en el estándar.

4.5 Promociones integrales [conv.prom]

Un prvalue de un tipo entero distinto de bool , char16_t , char32_t o wchar_t cuyo rango de conversión entera (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 de fuente ; de lo contrario, el prvalue fuente se puede convertir a un valor prvalue de tipo unsigned int .

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

Así es como se ve 2147483648 en binario.

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

Como -2147483648 es en realidad 2147483648 con negación ( - ) aplicada, el número no es el esperado. En realidad, es el equivalente de este pseudocódigo: operator -(2147483648)

Ahora, suponiendo que su comstackdor tenga sizeof(int) igual a 4 y CHAR_BIT se define como 8 , eso haría que 2147483648 desborde el máximo valor de un entero ( 2147483647 ). Entonces, ¿cuál es el máximo más uno? Vamos a trabajar en eso con un entero de cumplidos de 4 bits.

¡Espere! 8 desborda el entero! qué hacemos? Use su representación sin signo de 1000 e interprete los bits como un entero con signo. Esta representación nos deja con -8 aplicando la negación complemento 2 que resulta en 8 , que, como todos sabemos, es mayor que 0 .

Esta es la razón por la cual (y ) comúnmente definen INT_MIN como ((-2147483647) - 1) – de modo que el entero máximo con signo ( 0x7FFFFFFF ) es negado ( 0x80000001 ), luego disminuido ( 0x80000000 ).