2017-06-23 5 views
1

Selon ce link, l'exécution de l'opération de division INT_MIN/-1 entraînera la fin du programme dans les CPU i386. Mon processeur est d'architecture 32 bits et j'utilise le compilateur GCC. J'ai fait les expériences suivantes pour le vérifier.Quelle est la différence entre effectuer une opération de division sur les constantes et les variables

int a = INT_MIN; 
int b = -1; 
int c = a/b; 
printf("%d\n",c); 

Selon les informations spécifiées dans le lien ci-dessus de ce programme obtient lancer une exception mis fin à virgule flottante. Mais ce n'était pas pareil quand je l'ai essayé d'une manière différente.


int c = INT_MIN/-1; 
printf("%d\n",c); 

Le compilateur a jeté l'avertissement suivant après la compilation de ce programme.

iso.c: En fonction « principale »:
iso.c: 6: 18: avertissement: débordement d'entier dans l'expression [-Woverflow]
int c = INT_MIN/-1;
_____________^

Mais je suis la sortie -2147483648. Encore une fois, j'ai fait plus de deux expériences.


int a = INT_MIN; 
int b = -1; 
printf("%d\n",a/b); 

Ce fut une exception à virgule flottante.


printf("%d\n",INT_MIN/-1); 

Ce jeté l'avertissement du compilateur suivant.

iso.c: En fonction 'principale':
iso.c: 6: 24: avertissement: débordement d'entier dans l'expression [-Woverflow]
printf ("% d \ n", INT_MIN/- 1);
__________________^

Et la sortie de ce programme a été à nouveau -2147483648.


Après avoir fait toutes ces expériences, je l'ai remarqué que résultat de l'opération de division fait directement sur des constantes diffère du résultat de l'opération de division fait sur les variables. Alors, qu'est-ce qui fait exactement la différence?

+1

Les compilateurs peuvent être intelligents et reconnaissent que cette partie 'int a = INT_MIN; int b = -1; int c = a/b; 'peut être fait par le compilateur, pas par le CPU, donc vous avez déjà un résultat lors de l'exécution du programme et la divison n'est même pas effectuée. D'autre part, si la valeur de la variable n'est pas connue avant la division ('scanf' pour la valeur de lecture d'entrée) alors l'instruction de division sera faite à coup sûr. – tilz0R

Répondre

5

Les deux résultats sont acceptables selon la norme. Projet n1256 pour C99 dit (mettre l'accent sur le mien):

6,5 expressions
...
5 Si une condition d'exception se produit lors de l'évaluation d'une expression (qui est, si le résultat est pas mathématiquement définie ou pas dans la plage des valeurs représentables pour son type ), le comportement n'est pas défini.

Dans la représentation entière du complément de 2, INT_MIN/-1 est INT_MAX + 1 si l'opération invoque un comportement non défini, de sorte que tout résultat (y compris l'accident) est acceptable

Comme l'a expliqué @ tilz0R dans son commentaire, lorsque les valeurs sont transmises dans variables, l'opération est exécutée au moment de l'exécution et déclenche un signal SIGFPE. Mais lorsque l'opération implique uniquement des constantes de temps de compilation, l'opération est exécutée par le compilateur au moment du compilateur. Dans l'implémentation de gcc, le compilateur se protège contre l'erreur et utilise simplement sa meilleure représentation pour INT_MAX + 1. Dans une implémentation complémentaire de 32 bits 2, INT_MAX est 0x7fffffff, donc INT_MAX + 1 est (après débordement signé) 0x80000000 ou INT_MIN (-2147483648)