No se puede asignar -2147483648 a una variable de tipo long long

Estoy comstackndo el código a continuación y por alguna razón no puedo asignar -2147483648 a la variable que tiene 8 bytes de largo y está firmada.

long long x = -2147483648; 

Cuando paso sobre esta línea, el valor de x es 2147483648 y la ventana ‘Ver’ en MS Visual Studio muestra que el tipo de x es __int64. Un sizeof (x) también devuelve 8.

Según limit.h los límites para un largo largo firmado son:

 #define LLONG_MAX 9223372036854775807i64 /* maximum signed long long int value */ #define LLONG_MIN (-9223372036854775807i64 - 1) /* minimum signed long long int value */ 

y:

 /* minimum signed 64 bit value */ #define _I64_MIN (-9223372036854775807i64 - 1) /* maximum signed 64 bit value */ #define _I64_MAX 9223372036854775807i64 

¡¡¡Simplemente no entiendo!!!

¿Alguien por favor puede arrojar algo de luz sobre esto?

Sin el LL, el comstackdor parece deducir que 2147483648 es un unsigned long 32 bits. Entonces aplica el - operador. El resultado es 0 - 2147483648 . Dado que es menor que 0 y al ser una unsigned long t , se agrega 4294967296 , que es 2147483648 nuevamente. Este valor se asigna entonces a long long x .

Sugerir:

 long long x = -2147483648LL; // or long long x = -2147483647 - 1; 

Intenta asignarlo a -2147483648LL

ver constantes enteras aquí

Su código comstack y ejecuta bien en mi comstackdor GCC 4.6.3, con –std = c99. Sospecho que está utilizando el llamado comstackdor de C en lugar de desesperación que Microsoft suministra. Obviamente no es muy inteligente. Use un sufijo largo y largo ( i64 , ll o LL ) para engañarlo para que se comporte.

Curiosamente, el comstackdor de MS C ++ tampoco puede obtener este derecho:

 #include  int main() { long long x = -2147483647; std::cout << x << std::endl; x = -2147483648; std::cout << x << std::endl; x = -2147483649; std::cout << x << std::endl; return 0; } 

Salida

 -2147483647
 2147483648
 2147483647

Compilé esto con el comstackdor x86 C ++ de VS2013.

Y obtengo el mismo resultado de mi g ++ 4.6.3.

Así que creo que hay más de esto de lo que parece. Espero que alguien que sepa más que yo pueda explicar todo esto.

En respuesta a algunos de los otros comentarios (lo siento, no puedo responder a cada uno de ellos porque todavía no tengo suficiente representante):

En C y C ++, el tipo de expresión no depende de su contexto. En este caso, el tipo de -214743648 está definido por las reglas de idioma, el hecho de que luego lo asigne a un long long no afecta esto.

En realidad, esta forma de hacer las cosas hace que el lenguaje sea mucho más simple que la alternativa, es una de las cosas que me atrajo a C en primer lugar.

En el ejemplo de David Hefernan,

 x = -2147483648; std::cout << x << std::endl; // gives 2147483648 x = -2147483649; std::cout << x << std::endl; // gives 2147483647 

Lo importante es que el signo - NO es parte de un literal entero. La expresión 2147483648 es una constante entera cuyo tipo se determina de acuerdo con un conjunto de reglas en el estándar; y luego el operador unario menos se aplica al valor (que no cambia su tipo).

Desafortunadamente, C90, C99, C ++ 98 y C ++ 11 tienen reglas diferentes para los tipos de literales enteros. Además, las reglas son diferentes para las constantes decimales que para las constantes hexales u octales. Puede consultarlos en los documentos de normas relevantes.

Si tiene ints de 32 bits, entonces 2147483648 es demasiado grande para ser un int . En todos los dialectos, el siguiente tipo posible es long int . Si también tiene long ints 32 bits, en C99 o C ++ 11 tiene el tipo long long int . En C90 o C ++ 98 tiene el tipo unsigned long int . (Esos idiomas no tienen un tipo long long ).

Volver al ejemplo de David Heffernan. C ++ 98 no tiene long long , por lo tanto, o estás usando un comstackdor de C ++ 11 o usando las extensiones de Microsoft. Asumiendo esto último; quién sabe qué decidieron hacer para las constantes enteras, pero si han conservado la definición de C ++ 98 de que 2147483648 tiene el tipo unsigned long int , eso explicaría los resultados.

Resulta que tuve que escribirlo así:

 long long x = -2147483648i64; 

¿Por qué el comstackdor no es capaz de resolverlo? Ya especifiqué el tipo, ¿por qué tengo que poner ‘i64’ después del número?