C le comportement de dépassement d'entier lors de l'affectation à des nombres entiers de plus grande largeur

StackOverflow https://stackoverflow.com/questions/728847

Question

Si j'exécute le code suivant dans C:

#include <stdint.h>

uint16_t a = 4000;
uint16_t b = 8000;

int32_t c = a - b;

printf("%d", c);

Il imprime correctement « -4000 » comme résultat. Cependant, je suis un peu confus: ne devrait pas y avoir un dépassement arithmétique lors de la soustraction d'un entier non signé plus de l'autre? Quelles sont les règles de coulée sont en jeu ici? Cette question semble un peu noobish, de sorte que toute référence serait grandement apprécié.

Était-ce utile?

La solution

La question est en fait un peu compliqué. Opérandes d'expressions arithmétiques sont converties en utilisant des règles spécifiques que vous pouvez voir dans la section 3.2.1.5 de la standard (C89) . Dans votre cas, la réponse dépend de ce que l'uint16_t type est. Si elle est plus petite que int, disons short int, puis les opérandes sont convertis en int et vous obtenez -4000, mais sur un système 16 bits, uint16_t pourrait être unsigned int et la conversion à un type signé ne se produira pas automatiquement.

Autres conseils

La réponse courte est que ceux-ci sont tous promus int au cours de la soustraction. Pour la longue réponse, regardez la section 6.3.1.1 de la C norme , où il parle de promotions entières dans les expressions arithmétiques. langue pertinente de la norme:

  

Si int peut représenter toutes les valeurs de   le type d'original, la valeur est   converti en un int ; sinon, il est   converti en un unsigned int . Celles-ci   sont appelés les promotions entières .   Tous les autres types sont inchangés par la   promotions entières.

Les détails sont là aussi, mais ils obtiennent assez méchant.

Les deux opérandes sont promus à int32_t au cours de la soustraction. Si le résultat avait été plus grande que la valeur maximale pour int32_t vous avez vu trop-plein.

Il y a, en fait, un trop-plein, mais C ne vous dit pas.

Le débordement laisse une valeur qui se trouve être -4000 quand interprété comme un entier signé. Cela fonctionne comme prévu sur les machines de complément de 2.

Essayez d'interpréter le résultat comme non signé, et vous remarquerez que (u1-u2) évalue à un nombre apparemment sans rapport quand u1

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