251 votes

Pourquoi est-0 <-0 x 80000000 ?

Je l’ai Voici un programme simple :

La condition `` est toujours true. Comment est-ce possible ?

Il fonctionne très bien si je change de la macro :

Quelqu'un peut-il indiquer le numéro ?

361voto

Lundin Points 21616

C'est assez subtile.

Chaque littéral entier dans votre programme a un type. Le type a est réglementée par une table dans 6.4.4.1:

Suffix      Decimal Constant    Octal or Hexadecimal Constant

none        int                 int
            long int            unsigned int
            long long int       long int
                                unsigned long int
                                long long int
                                unsigned long long int

Si un nombre littéral ne peut pas s'adapter à l'intérieur de la valeur par défaut int type, il va tenter à la prochaine grande type comme indiqué dans le tableau ci-dessus. Donc, pour l'ordinaire entier décimal littéraux il va comme:

  • Essayez int
  • Si elle ne rentre pas, essayez long
  • Si elle ne rentre pas, essayez long long.

Hex littéraux de se comporter différemment si! Si le littéral ne peut pas s'adapter à l'intérieur d'un type signé comme int, il va d'abord essayer d' unsigned int avant de passer à essayer de plus grands types. Voir la différence dans le tableau ci-dessus.

Ainsi, sur un système 32 bits, votre littérale 0x80000000 est de type unsigned int.

Cela signifie que vous pouvez appliquer unaire - de l'opérateur sur le littéral, sans invoquer de mise en œuvre définies par le comportement, comme vous le feriez lors de l'débordement d'un entier signé. Au lieu de cela, vous obtenez la valeur 0x80000000, une valeur positive.

bal < INT32_MIN invoque l'habitude de l'arithmétique de conversions et le résultat de l'expression -0x80000000 est promu unsigned int de long long. La valeur 0x80000000 est conservé et 0 est inférieure à 0x80000000, d'où le résultat.

Lorsque vous remplacez le littéral avec 2147483648L vous utilisez la notation décimale et donc le compilateur ne pioche pas de unsigned int, mais plutôt essaie de l'adapter à l'intérieur d'un long. Aussi le L suffixe dit que vous voulez un long si possible. La L suffixe a effectivement des règles similaires si vous continuez à lire mentionnés table dans 6.4.4.1: si le numéro ne correspond pas à l'intérieur de la demande long, il n'est pas dans les 32 bits de cas, le compilateur va vous donner un long long où il a mis en place.

27voto

Bathsheba Points 23209

est un littéral avec valeur 2147483648.

Appliquant le moins unaire sur ce encore vous donne un type non signé, avec une valeur différente de zéro. (En fait, pour une valeur non nulle , est la valeur que vous vous retrouvez avec .)

23voto

Vlad from Moscow Points 36219

Cet entier littéral 0x80000000 type unsigned int.

Selon la Norme (6.4.4.1 constantes entières)

5 Le type d'une constante entière est la première de l'correspondant liste dans laquelle sa valeur peut être représentée.

Et cette constante entière peut être représenté par le type d' unsigned int.

De sorte que cette expression

-0x80000000 a le même unsigned int type. En outre, il a la même valeur 0x80000000 dans le complément à deux de la représentation qui calcule de la façon suivante

-0x80000000 = ~0x80000000 + 1 => 0x7FFFFFFF + 1 => 0x80000000

Cela a un effet secondaire s'écrire par exemple

int x = INT_MIN;
x = abs( x );

Le résultat sera à nouveau INT_MIN.

Ainsi, dans cette condition

bal < INT32_MIN

il est comparé 0 avec unsigned valeur 0x80000000 convertis en type long long int, selon les règles de l'arithmétique habituelle des conversions.

Il est évident que 0 est inférieure à 0x80000000.

12voto

dbush Points 8590

La constante numérique est de type . Si nous prenons `` et faire 2 s complimenter math là-dessus, nous obtenons ceci :

Donc . Et en comparant (puisque `` n’est pas signé) est vrai.

11voto

chux Points 13185

D'un point de confusion se produit dans la pensée de l' - fait partie de la constante numérique.

Dans le code ci-dessous 0x80000000 est la constante numérique. Son type est de déterminer uniquement sur cela. L' - est appliquée par la suite et ne change pas le type.

#define INT32_MIN        (-0x80000000)
long long bal = 0;
if (bal < INT32_MIN )

Raw sans fioritures constantes numériques sont positifs.

Si c'est décimal, puis le type attribué est le premier type qui va la tenir: int, long, long long.

Si la constante est en octal ou en hexadécimal, il obtient le premier type qui la tient: int, unsigned, long, unsigned long, long long, unsigned long long.

0x80000000, OP système obtient le type d' unsigned ou unsigned long. De toute façon, c'est un certain type non signé.

-0x80000000 est également une valeur non nulle et d'être certain type non signé, il est plus grand que 0. Lorsque le code compare à un long long, les valeurs ne sont pas modifiées sur les 2 côtés de la comparer 0 < INT32_MIN est vrai.


Une autre définition évite ce curieux comportement

#define INT32_MIN        (-2147483647 - 1)

Nous marchons dans la terre de fantaisie pour un temps où l' int et unsigned sont de 48 bits.

Ensuite, 0x80000000 correspond int et est donc le type d' int. -0x80000000 est un nombre négatif et le résultat de l'impression est différente.

[Réel]

Depuis 0x80000000 s'inscrit dans certains type non signé devant un type signé, comme il est juste plus grand que some_signed_MAX encore dans some_unsigned_MAX, c'est un certain type non signé.

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