249 votes

(-2147483648> 0) renvoie true en C ++?

-2147483648 est le plus petit entier de type entier 32 bits, mais il semble qu'elle déborde dans l' if(...) phrase:

if (-2147483648 > 0)
    std::cout << "true";
else
    std::cout << "false";

Cela permettra d'imprimer true lors de mes tests. Cependant, si on jette de -2147483648 à l'entier, le résultat sera différent:

if (int(-2147483648) > 0)
    std::cout << "true";
else
    std::cout << "false";

Cela permettra d'imprimer false.

Je suis confus. Quelqu'un peut-il donner une explication à ce sujet?


Mise à jour 02-05-2012:

Merci pour vos commentaires, à mon compilateur, de la taille d'un int fait 4 octets. Je suis à l'aide de VC pour certains 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 détaillée sur la façon dont le compilateur comportement sur cette entrée, et comment ce minimum entier a été mis en œuvre. qPCR4vir sur l'autre main a donné quelques "curiosités" et comment les entiers sont représentés. Tellement impressionnant!

398voto

AndreyT Points 139512

-2147483648 n'est pas un "nombre". Langage C++ ne prend pas en charge négative des valeurs littérales.

-2147483648 est en fait une expression positive de la valeur littérale 2147483648 avec unaire - opérateur en face d'elle. Valeur en 2147483648 est apparemment trop grande pour le côté positif de l' int gamme sur votre plate-forme. Si le type long int avaient une plus grande gamme de votre plate-forme, le compilateur aurait à assumer automatiquement que 2147483648 a long int type. (En C++11, le compilateur devra aussi considérer long long int type.) Dans ce cas, le compilateur pour évaluer -2147483648 dans le domaine de plus le type et le résultat serait négatif, que l'on pourrait attendre.

Cependant, apparemment, dans votre cas, la gamme de long int est la même que la gamme de int, et en général il n'y a pas de type entier avec une plus grande portée que int sur votre plate-forme. Cette formellement signifie que la constante positive 2147483648 débordements de tous signés types d'entiers, 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 indéfini dans de tels cas, au lieu d'exiger un message de diagnostic, mais c'est la façon dont il est.)

Dans la pratique, en tenant compte du fait que le comportement est indéfini, 2147483648 pourrait obtenir de l'interpréter comme une mise en œuvre dépendant de la valeur négative qui est positif après avoir unaire - lui est appliquée. Par ailleurs, certaines implémentations peuvent décider d'essayer d'utiliser unsigned types pour représenter la valeur (par exemple, en C89/90 compilateurs ont été nécessaires à l'utilisation de unsigned long int, mais pas en C99 ou C++). Les implémentations sont autorisés à faire n'importe quoi, puisque le comportement est indéfini de toute façon.

Comme une note de côté, c'est la raison pour laquelle les constantes comme INT_MIN sont généralement définis comme

#define INT_MIN (-2147483647 - 1)

au lieu de ce qui semble plus simple

#define INT_MIN -2147483648

Ce dernier ne fonctionnerait pas comme prévu.

44voto

qPCR4vir Points 2421

Le compilateur (VC2012) promouvoir le "minimum" des entiers qui peut contenir les valeurs. Dans le premier cas, signed int (et long int) ne peut pas (avant le panneau est appliqué), mais unsigned int pouvez: 2147483648 a unsigned int ???? type. Dans le deuxième vous forcez int de la unsigned.

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

avertissement C4146: unaire moins opérateur de type non signé, résultat encore non signé

Ici sont liées "curiosités":

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

C++11 standard:

2.14.2 les littéraux Entiers [lex.icône]

...

Un entier littéral est une séquence de chiffres qui n'a pas de période ou l'exposant de la partie. Un littéral entier peut avoir un préfixe qui indique son de base et d'un suffixe qui indique son type.

...

Le type d'un entier littéral est le premier de la liste correspondante dans lequel sa valeur peut être représentée.

enter image description here

Si un entier littéral ne peut pas être représenté par n'importe quel type dans sa liste et une extension de type entier (3.9.1) peut représenter sa valeur, il peut ont qui s'étendait de type entier. Si tous les types dans la liste pour le littéral sont signés, l'étendue de type entier doit être signé. Si tous les types de dans la liste pour le littéral ne sont pas signés, l' étendue de type entier doit être signé. Si la liste contient à la fois entiers signés et non signés, l'étendue de type entier peut être signé ou non signé. Un programme est mal formé si l'une de ses unités de traduction contient un entier littéral qui ne peuvent pas être représentés par l'un des les types autorisés.

Et ce sont les promotions règles pour les entiers dans la norme.

4.5 Intégrale des promotions [conv.bal]

Un prvalue d'un entier de type autre que bool, char16_t, char32_t, ou wchar_t dont la conversion d'entier rang (4.13) est inférieur au rang de int peut être converti en prvalue de type int si int peut représenter toutes les valeurs du type de source; sinon, la source prvalue peut être converti en prvalue de type unsigned int.

6voto

martini Points 847

En bref, 2147483648 déborde à -2147483648 , et (-(-2147483648) > 0) est true .

C'est ainsi que 2147483648 ressemble à un 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.

4voto

Cole Johnson Points 3671

Parce qu' -2147483648 est en fait 2147483648 avec en complément à deux de la négation (-), le nombre n'est pas ce que vous attendez. C'est en fait l'équivalent de ce pseudo-code: operator -(2147483648)

Maintenant, en supposant que votre compilateur a sizeof(int) égal à 4 et CHAR_BIT est défini comme 8, qui ferait 2147483648 de dépassement du maximum de la valeur signée d'un nombre entier (2147483647). Alors, quel est le maximum de plus un? Permet de travailler qu'avec un 4 bits, 2s compliment entier.

Attendez! 8 débordements d'entier! Que faisons-nous? Utiliser son unsigned représentation de l' 1000 et interpréter les bits d'un entier signé. Cette représentation nous laisse avec -8 appliqué les 2 de compléter la négation résultant en 8, ce qui, comme nous le savons tous, est plus grand que 0.

C'est pourquoi, <limits.h> (et <climits>), communément définir INT_MIN comme ((-2147483647) - 1) - alors que le maximum des entiers signés (0x7FFFFFFF) est annulé (0xFFFFFFFE), alors décrémenté (0xFFFFFFFF).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X