Impossible d’affecter -2147483648 à une variable de type long long

Je comstack le code ci-dessous et pour une raison quelconque, je ne peux pas affecter -2147483648 à la variable de 8 octets de long et signée.

long long x = -2147483648; 

Lorsque je survole cette ligne, la valeur de x est 2147483648 et la fenêtre “Visualiser” de MS Visual Studio indique que le type de x est __int64. Un sizeof (x) renvoie également 8.

Selon limit.h, les limites pour un long long signé sont:

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

et:

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

Je ne comprends tout simplement pas !!!

Quelqu’un peut-il s’il vous plaît nous éclairer?

Sans le LL, le compilateur semble en déduire que 2147483648 est un unsigned long 32 bits. Ensuite, il applique l’opérateur - . Le résultat est 0 - 2147483648 . 4294967296 est ajouté, ce qui correspond à 2147483648 car il est inférieur à 0 et qu’il s’agit d’un unsigned long t . Cette valeur est ensuite assignée à long long x .

Suggérer:

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

Essayez d’atsortingbuer à -2147483648LL

voir les constantes entières ici

Votre code se comstack et s’exécute correctement sur mon compilateur GCC 4.6.3, avec –std = c99. Je suppose que vous utilisez le prétendu compilateur C, plutôt sans espoir, fourni par Microsoft. Ce n’est évidemment pas très intelligent. Utilisez un long suffixe long ( i64 , ll ou LL ) pour le tromper.

Fait intéressant, le compilateur MS C ++ ne peut pas obtenir ce droit non plus:

 #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; } 

Sortie

 -2147483647
 2147483648
 2147483647

Je l'ai compilé avec le compilateur C ++ x86 de VS2013.

Et je reçois le même résultat de mon g ++ 4.6.3.

Donc, je pense qu'il y a plus que cela à regarder. J'espère que quelqu'un qui en sait plus que moi pourrait expliquer tout cela.

En réponse à d’autres commentaires (désolé, je ne peux pas répondre à chacun d’entre eux car je n’ai pas encore assez de représentants):

En C et C ++, le type d’une expression ne dépend pas de son contexte. Dans ce cas, le type de -214743648 est défini par les règles de langage, le fait que vous l’ -214743648 plus tard long long ne change rien à cela.

En fait, cette façon de faire rend le langage beaucoup plus simple que l’alternative, c’est une des choses qui m’a attiré vers C en premier lieu.

Dans l’exemple de David Heffernan,

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

L'important est que le signe - ne fasse PAS partie d'un littéral entier. L'expression 2147483648 est une constante de type entier dont le type est déterminé selon un ensemble de règles de la norme. et ensuite l'opérateur unaire moins est appliqué à la valeur (ce qui ne change pas son type).

Malheureusement, C90, C99, C ++ 98 et C ++ 11 ont des règles différentes pour les types de littéraux entiers. De plus, les règles sont différentes pour les constantes décimales que pour les constantes hex ou octales! Vous pouvez les rechercher dans les documents de normes pertinents.

Si vous avez des ints de 32 bits, alors 2147483648 est trop volumineux pour être un int . Dans tous les dialectes, le prochain type possible est long int . Si vous avez également long ints 32 bits, alors en C99 ou C ++ 11, il a le type long long int . En C90 ou C ++ 98, le type unsigned long int . (Ces langues n'ont pas un type long long ).

Revenons à l'exemple de David Heffernan. C ++ 98 n'est pas long long , vous utilisez donc un compilateur C ++ 11 ou utilisez des extensions Microsoft. En supposant ce dernier; qui sait ce qu’ils ont décidé de faire pour les constantes de nombre entier, mais s’ils ont conservé la définition C ++ 98 selon laquelle 2147483648 est de type unsigned long int , cela expliquerait les résultats.

Il s’avère que je devais juste l’écrire comme ceci:

 long long x = -2147483648i64; 

Pourquoi le compilateur n’est-il pas en mesure de le comprendre? J’ai déjà épelé le type, alors pourquoi dois-je mettre «i64» après le nombre ???