true false c++ overflow

c++ - false - boolean en c



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

-2147483648 es el 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 compilador, el tamaño de int es de 4 bytes. Estoy usando VC para algunas pruebas simples. He cambiado la descripción en mi pregunta.

Eso es un montón de AndreyT muy buenas en esta publicación, AndreyT dio una explicación muy detallada sobre cómo se comportará el compilador en dicha entrada y cómo se implementó este entero mínimo. qPCR4vir otro lado, qPCR4vir proporcionó algunas "curiosidades" relacionadas y cómo se representan los enteros. ¡Tan impresionante!


Debido a que -2147483648 es en realidad 2147483648 con negación ( - ) aplicada, el número no es el que esperaría. En realidad, es el equivalente de este pseudocódigo: operator -(2147483648)

Ahora, suponiendo que su compilador tiene un sizeof(int) igual a 4 y CHAR_BIT se define como 8 , eso haría que 2147483648 desbordara el valor con signo máximo de un número entero ( 2147483647 ). Entonces, ¿cuál es el máximo más uno? Permite resolver eso con un entero de 4 bits y 2 complementos.

¡Espere! 8 desborda el entero! qué hacemos? Utilice 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 del complemento a 2, lo que da como resultado 8 , que, como todos sabemos, es mayor que 0 .

Es por esto que <limits.h> (y <climits> ) comúnmente definen INT_MIN como ((-2147483647) - 1) - para que el entero con signo máximo ( 0x7FFFFFFF ) se 0x80000001 ( 0x80000001 ), y luego disminuya ( 0x80000000 ).


El compilador (VC2012) promueve a 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 forzas int desde el unsigned .

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

advertencia C4146: operador unario menos aplicado al tipo sin signo , el resultado sigue sin firmar

Aquí están relacionadas "curiosidades":

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

...

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

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 todos los tipos en la lista para el literal están firmados, el tipo entero extendido deberá estar firmado. Si todos los tipos en la lista para el literal están sin firmar, el tipo de entero extendido será sin firmar. Si la lista contiene tipos firmados y sin firmar, el tipo entero extendido puede estar firmado o sin firmar. Un programa está mal formado si una de sus unidades de traducción contiene un literal entero que no puede representarse por ninguno de los tipos permitidos.

Y estas son las reglas de promociones 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 de entero (4.13) es menor que el rango de int puede convertirse en un prvalue de tipo int si int puede representar todos los valores del tipo fuente ; de lo contrario, el valor de origen se puede convertir en un valor de tipo unsigned int .


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

This es como se ve 2147483648 en binario.

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


-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 delante de él. El valor 2147483648 es aparentemente demasiado grande para el lado positivo del rango int en su plataforma. Si el tipo long int tenía un mayor rango en su plataforma, el compilador tendría que asumir automáticamente que 2147483648 tiene el tipo long int . (En C ++ 11, el compilador también tendría que considerar el tipo long long int ). Esto haría que el compilador evalúe -2147483648 en el dominio de tipo más grande y el resultado sería negativo, como uno esperaría.

Sin embargo, aparentemente, en su caso, el rango de long int es el mismo que el rango de int , y en general no hay un tipo entero con mayor rango que int en su 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 de idioma opte por un comportamiento indefinido en tales casos, en lugar de requerir un mensaje de diagnóstico, pero así es).

En la práctica, teniendo en cuenta que el comportamiento no está definido, 2147483648 puede interpretarse como un valor negativo dependiente de la implementación que se vuelve positivo después de haber sido aplicado de forma unaria. Alternativamente, algunas implementaciones pueden decidir intentar usar tipos sin signo para representar el valor (por ejemplo, en C89 / 90 se requirió que los compiladores usen unsigned long int , pero no en C99 o C ++). Las implementaciones pueden hacer cualquier cosa, ya que el comportamiento es indefinido de todos modos.

Como nota al margen, esta es la razón por la cual las constantes como INT_MIN se definen típicamente como

#define INT_MIN (-2147483647 - 1)

en lugar de lo aparentemente más sencillo

#define INT_MIN -2147483648

Este último no funcionaría como estaba previsto.