Visual Studio 2015 – Avertissement du compilateur (niveau 2) C4146

J’ai la ligne suivante dans mon code

signed int test_case= -2147483648; 

qui génère l’erreur:

C4146 opérateur unaire moins appliqué au type non signé, résultat toujours non signé

mais c’est toujours avec la plage de données du type entier signé:

__int32 signé, signé int, int –2 147 483 648 à 2 147 483 647

Les choses étranges est de l’atsortingbuer comme signé long donne cette même erreur, à savoir

 signed long test_case= -2147483648; 

Les modifications ci-dessous comstacknt OK:

 signed int test_case= -2147483647; signed int test_case= 2147483649; signed long test_case= -214748364800; 
  • Quelqu’un at-il vu ce problème avec le compilateur Visual Studio 2015?
  • Comment définit-il les types de données?
  • Comment la gamme est-elle vérifiée?
  • Pourquoi semble-t-il ignorer la cession “signée”?

Merci

Puisqu’il s’agit d’un bogue du compilateur, cette réponse est spécifique à MSVC et est fausse du sharepoint vue iso C ++. Pour la réponse correcte et standard, veuillez consulter la réponse de @Bathsheba. (J’encourage le PO à accepter la bonne réponse au lieu de cette réponse pour les futurs lecteurs).


De MSDN :

Le nombre 2147483648 est évalué. Parce qu’il est supérieur à la valeur entière maximale de 2147483647, le type de 2147483648 n’est pas int, mais unsigned int.

En d’autres termes, le compilateur traitera -2147483648 en tant que - et 2147483648 pas en tant que -2147483648 . Donc, la partie 2147483648 est considérée comme unsigned int car elle est plus grande que int . puis le compilateur applique l’opérateur - qui mène à cet avertissement.

Solution:

 auto test_case= -2147483648ll; 

C’est un bug du compilateur.

Première chose à noter: -2147483648 n’est pas un littéral. Il n’existe pas de littéral négatif en C ++.

-2147483648 est une expression constante évaluable à la compilation, composée de 2147483648 et de l’opérateur unaire moins.

Sur les MSVC ciblant Windows x64 (où int et long sont tous deux 32 bits), 2147483648 devrait être long long int , de sorte que -2147483648 le serait également. Je crois comprendre que la norme insiste sur un type signé, sauf si vous utilisez un littéral hexadécimal ou octal.

La conversion ressortingctive en signed int est, dans ce cas, bien définie puisque vous ciblez une plate-forme avec un type int complémentaire 32 bits 2.

Autres références: voir http://en.cppreference.com/w/cpp/language/integer_literal