2009-04-08 12 views
7

Si j'exécute le code suivant dans C:entier C comportement de débordement lors de l'affectation à des entiers plus grande largeur

#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-il pas y avoir un débordement arithmétique lors de la soustraction d'un entier non signé plus grand de l'autre? Quelles règles de casting sont en jeu ici? Cette question semble un peu noobish, donc toutes les références seraient grandement appréciées.

Répondre

5

Le problème est en fait un peu compliqué. Les opérandes d'expressions arithmétiques sont convertis en utilisant des règles spécifiques que vous pouvez voir dans la section 3.2.1.5 du Standard (C89). Dans votre cas, la réponse dépend de ce qu'est le type uint16_t. S'il est inférieur à int, disons short int, alors 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 en type signé ne se ferait pas automatiquement.

+0

Ma référence est bien sûr à l'ancienne norme. Voir la réponse de tgamblin pour C99. Bien qu'ils disent la même chose. – TrayMan

+0

3.2.1.5 est pour les conversions double/float/int/etc. Il cherche des promotions intégrales (long/int/char/short/etc) qui sont en 3.2.1.1 de cette version de la norme. C'est en 6.3.1.1 dans la nouvelle norme que j'ai liée à ci-dessus. – tgamblin

+0

Il pourrait également vouloir 3.2.1.2 aussi (ints signés/non signés) – tgamblin

1

Les deux opérandes sont promus à int32_t pendant la soustraction. Si le résultat avait été supérieur à la valeur maximale pour int32_t, vous auriez vu un débordement.

3

La réponse courte est que tous sont promus à int pendant la soustraction. Pour la réponse longue, regardez la section 6.3.1.1 du C standard, où il est question de promotions entières dans les expressions arithmétiques. langue pertinente de la norme:

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

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

0

Il y a, en fait, un débordement mais C ne vous le dit pas. Le dépassement de capacité laisse une valeur égale à -4000 lorsqu'il est interprété comme un entier signé. Cela fonctionne comme prévu sur les machines à complément de 2. Essayez d'interpréter le résultat comme non signé, et vous remarquerez que (u1-u2) évalue à un certain nombre apparemment sans lien lorsque u1 < u2.