-2147483648 est le plus petit entier pour le type entier avec 32 bits, mais il semble qu'il débordera dans la if(...)
phrase:
if (-2147483648 > 0)
std::cout << "true";
else
std::cout << "false";
Cela s'imprimera true
dans mes tests. Cependant, si nous convertissons -2147483648 en entier, le résultat sera différent:
if (int(-2147483648) > 0)
std::cout << "true";
else
std::cout << "false";
Cela s'imprimera false
.
Je suis confus. Quelqu'un peut-il donner une explication à ce sujet?
Mise à jour 02-05-2012:
Merci pour vos commentaires, dans mon compilateur, la taille de int est de 4 octets. J'utilise VC pour des tests simples. J'ai changé la description dans ma question.
C'est beaucoup de très bonnes réponses dans ce post, AndreyT a donné une explication très détaillée sur la façon dont le compilateur se comportera sur une telle entrée, et comment cet entier minimum a été implémenté. qPCR4vir , d'autre part, a donné quelques "curiosités" et comment les nombres entiers sont représentés. Tellement impressionnant!
la source
INT_MIN
de-9223372036854775808
, siCHAR_BIT
est 16. Et même avecCHAR_BIT == 8
etsizeof(int
== 4) `vous pouvez obtenir-9223372036854775807
parce que C ne nécessite pas de nombres à 2 compléments.Réponses:
-2147483648
n'est pas un "nombre". Le langage C ++ ne prend pas en charge les valeurs littérales négatives.-2147483648
est en fait une expression: une valeur littérale positive2147483648
avec un-
opérateur unaire devant elle. La valeur2147483648
est apparemment trop grande pour le côté positif de laint
plage sur votre plate-forme. Si le typelong int
avait une plus grande plage sur votre plateforme, le compilateur devrait automatiquement supposer qu'il2147483648
a lelong int
type. (En C ++ 11, le compilateur devrait également prendre en compte lelong long int
type.) Cela obligerait le compilateur à évaluer-2147483648
dans le domaine de type plus grand et le résultat serait négatif, comme on pourrait s'y attendre.Cependant, dans votre cas, la plage de
long int
est la même que la plage deint
, et en général, il n'y a pas de type entier avec une plage plus grande queint
sur votre plate-forme. Cela signifie formellement que la constante positive2147483648
déborde de tous les types d'entiers signés disponibles, ce qui signifie que le comportement de votre programme n'est pas défini. (Il est un peu étrange que la spécification du langage opte pour un comportement non défini dans de tels cas, au lieu d'exiger un message de diagnostic, mais c'est ainsi.)Dans la pratique, la prise en compte du fait que le comportement n'est pas défini
2147483648
peut être interprétée comme une valeur négative dépendante de l'implémentation qui devient positive après avoir été-
appliquée à l'unary. Alternativement, certaines implémentations peuvent décider d'essayer d'utiliser des types non signés pour représenter la valeur (par exemple, en C89 / 90, les compilateurs devaient utiliserunsigned long int
, mais pas en C99 ou C ++). Les implémentations sont autorisées à faire n'importe quoi, car le comportement n'est pas défini de toute façon.En remarque, c'est la raison pour laquelle les constantes comme
INT_MIN
sont généralement définies commeau lieu de ce qui semble plus simple
Ce dernier ne fonctionnerait pas comme prévu.
la source
#define INT_MIN (-2147483647 - 1)
.int
. L'implémentation d'OP peut ne pas avoir un type 64 bits.-1.0
c'est analysé comme une valeur double négative, n'est-ce pas?unsigned long int
dans ce contexte, mais en C99 cette autorisation a été supprimée. Les littéraux non suffixés en C et C ++ doivent avoir des types signés . Si vous voyez un type non signé ici quand un signé fonctionnerait, cela signifie que votre compilateur est cassé. Si vous voyez ici un type non signé alors qu'aucun type signé ne fonctionnerait, alors ce n'est qu'une manifestation spécifique d'un comportement non défini.Le compilateur (VC2012) promeut les entiers "minimum" pouvant contenir les valeurs. Dans le premier cas,
signed int
(etlong int
) ne peut pas (avant l'application du signe), maisunsigned int
peut:2147483648
aunsigned int
???? type. Dans la seconde, vous forcez àint
partir duunsigned
.Voici des "curiosités" liées:
Norme C ++ 11 :
…
…
Et ce sont les règles de promotion des entiers dans la norme.
la source
int
,long int
,unsigned long int
pour représenter des constantes décimales unsuffixed. C'était le seul langage qui permettait d'utiliser des types non signés pour des constantes décimales non suffixées. En C ++ 98, c'étaitint
oulong int
. Aucun type non signé autorisé. Ni C (à partir de C99) ni C ++ ne permettent au compilateur d'utiliser des types non signés dans ce contexte. Votre compilateur est, bien sûr, libre d'utiliser des types non signés si aucun de ceux signés ne fonctionne, mais ce n'est encore qu'une manifestation spécifique d'un comportement non défini.int
oulong int
représenter2147483648
. En outre, AFAIK, dans VC2012 à la foisint
etlong int
sont de type 32 bits. Cela signifie que dans VC2012, le littéral2147483648
doit conduire à un comportement non défini . Lorsque le comportement n'est pas défini, le compilateur est autorisé à faire n'importe quoi. Cela signifierait que VC2012 n'est pas cassé. Il a simplement émis un message de diagnostic trompeur. Au lieu de vous dire que le comportement est indéfini, il a décidé d'utiliser un type non signé.long
et n'est pas obligé d'émettre un diagnostic? Cela semblerait cassé.En bref,
2147483648
déborde-2147483648
et(-(-2147483648) > 0)
esttrue
.Voilà à quoi
2147483648
ressemble en binaire.De plus, dans le cas de calculs binaires signés, le bit le plus significatif ("MSB") est le bit de signe. Cette question peut aider à expliquer pourquoi.
la source
Parce que
-2147483648
c'est en fait2147483648
avec la négation (-
) qui lui est appliquée, le nombre n'est pas celui que vous attendez. C'est en fait l'équivalent de ce pseudocode:operator -(2147483648)
Maintenant, en supposant que votre compilateur est
sizeof(int)
égal à4
etCHAR_BIT
est défini comme8
, cela ferait2147483648
déborder la valeur maximale signée d'un entier (2147483647
). Alors, quel est le maximum plus un? Permet de travailler avec un entier de complément de 4 bits et 2 s.Attendre! 8 déborde l'entier! Qu'est-ce qu'on fait? Utilisez sa représentation non signée
1000
et interprétez les bits comme un entier signé. Cette représentation nous laisse avec l'-8
application de la négation du complément 2s qui en résulte8
, qui, comme nous le savons tous, est supérieure à0
.C'est pourquoi
<limits.h>
(et<climits>
) se définissent généralementINT_MIN
comme((-2147483647) - 1)
- de sorte que l'entier signé maximum (0x7FFFFFFF
) soit nié (0x80000001
), puis décrémenté (0x80000000
).la source
-8
est toujours-8
.-(8)
lequel en C ++ est le même que-8
- c'est la négation appliquée à un littéral, pas un littéral négatif. Le littéral est8
, qui ne tient pas dans un entier signé de 4 bits, il doit donc être non signé. Le motif est1000
. Jusqu'à présent, votre réponse est correcte. La négation du complément à deux de1000
en 4 bits est1000
, peu importe si elle est signée ou non signée. Votre réponse, dit "interpréter les bits comme un entier signé" qui fait la valeur-8
après la négation du complément à deux, tout comme c'était avant la négation.8
. La négation est appliquée (modulo 16), ce qui donne une réponse finale de8
. L'encodage est toujours 1000 mais la valeur est différente car un type non signé a été choisi.