Question

J'ai effectué quelques tests dans VC++2010 en mélangeant des opérandes de différentes tailles qui provoquent un débordement lors d'une opération d'ajout :

int _tmain(int argc, _TCHAR* argv[])
{
    __int8 a=127;
    __int8 b=1;
    __int16 c=b+a;
    __int8  d=b+a;
    printf("c=%d,d=%d\n",c,d);

    return 0;
}

//result is: c=128, d=-128

Je ne comprends pas pourquoi c==128 !Je crois comprendre que dans les deux ajouts, b+a sont toujours considérés comme un ajout de 2 signés 8 bits variables.Le résultat est donc un débordement, c'est-à-dire-128. Après cela, le résultat est ensuite promu à 16 bits signé int pour la première opération d'affectation et c devrait toujours obtenir une valeur -128 de 16 bits.Ma compréhension est-elle correcte ?Le standard C++ est un peu difficile à lire.Le chapitre 4 semble parler de promotion intégrale mais je ne trouve rien en rapport avec cet exemple spécifique.

Était-ce utile?

La solution

Je crois comprendre que dans les deux ajouts, b+a sont toujours considérés comme un ajout de 2 variables signées de 8 bits.Le résultat est donc un débordement, c'est-à-dire-128.

Non, la promotion a lieu avant le + est évalué, pas après.L'addition se produit lorsque les deux a et b sont positifs.Les deux numéros sont promus au rang ints pour un ajout, ajouté sous forme de deux nombres positifs, puis converti en un court métrage de 16 bits.À aucun moment du processus le résultat ne devient négatif en raison d’un débordement, d’où le résultat final de 128.

Sans doute, cela a du sens :le comportement de a et b correspond à celui de deux nombres en mathématiques, ce qui le rend plus intuitif pour les praticiens des langues.

Autres conseils

C'est une promotion intégrale.

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

Dans cette déclaration

 __int16 c=b+a;

Tout d'abord, tout char et short int les valeurs sont automatiquement élevées à int.Ce processus est appelé promotion intégrale.Ensuite, tous les opérandes sont convertis jusqu'au type du plus grand opérande, appelé type de promotion.[Herbert Schildt]

Le valeurs de variables b et a sera promu à int puis l'opération s'applique à eux.

Dans la représentation entière à complément à deux, une valeur signée est représentée en définissant le bit le plus élevé.Cela permet à la machine d'ajouter et de soustraire des entiers binaires avec les mêmes instructions, que l'entier soit signé ou non.

  a = 127 == 0x7F == 0b01111111
+ b =   1 == 0x01 == 0b00000001
-------------------------------
  c = 128 == 0x80 == 0b10000000
  d =-128 == 0x80 == 0b10000000

Les variables c et d peuvent avoir différents types, mais différents types d'entiers ne sont que des interprétations différentes d'une seule valeur binaire.Comme vous pouvez le voir ci-dessus, la valeur binaire tient très bien sur 8 bits.Étant donné que la norme exige que les termes d'une expression mathématique soient étendus par zéro ou par signe (promu) à la taille d'un mot machine avant tous les calculs sont effectués et aucun des opérandes ne sera étendu par signe, le résultat est toujours 0b10000000 quel que soit le type des opérandes.

En résumé, la différence entre les résultats est que, pour un entier de 16 bits, le bit de signe est 0b1000000000000000 (lequel a+b n'en a pas), et pour un entier de 8 bits, le bit de signe est 0b10000000 (lequel a+b a).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top