Que se passe-t-il lorsque j'assigne long int à int en C?

dans un devoir récent, on m'a dit d'utiliser la variable long pour stocker un résultat, car il peut s'agir d'un grand nombre.

j'ai décidé de vérifier si cela comptait vraiment pour moi, sur mon système (Intel core i5/64-bit windows 7/gnu gcc compiler) et j'ai découvert que le code suivant:

printf("sizeof(char) => %dn", sizeof(char));
printf("sizeof(short) => %dn", sizeof(short));
printf("sizeof(short int) => %dn", sizeof(short int));
printf("sizeof(int) => %dn", sizeof(int));
printf("sizeof(long) => %dn", sizeof(long));
printf("sizeof(long int) => %dn", sizeof(long int));
printf("sizeof(long long) => %dn", sizeof(long long));
printf("sizeof(long long int) => %dn", sizeof(long long int));

produit la sortie suivante:

sizeof(char) => 1
sizeof(short) => 2
sizeof(short int) => 2
sizeof(int) => 4
sizeof(long) => 4
sizeof(long int) => 4
sizeof(long long) => 8
sizeof(long long int) => 8

En d'autres termes, sur mon système, int et long sont les mêmes, et tout sera trop grand pour int pour, sera trop grand pour long à tenir.

le travail à domicile en soi n'est pas la question ici. Je me demande Comment , sur un système où int < long , devrais-je attribuer un int à long?

je suis conscient du fait que il sont nombreux étroitement questions connexes à ce sujet, mais je pense que les réponses qu'elles contiennent ne me permettent pas de comprendre complètement ce qui se passera ou ce qui pourrait se produire dans le processus.

en gros, J'essaie de comprendre ce qui suit:

  1. doit-on remplacer long par int avant la cession, ou depuis long n'est pas un type de données différent, mais simplement un modificateur, il sera considérés comme inoffensifs pour affecter directement?
  2. que se passe-t-il sur les systèmes où long > int ? Le résultat sera Non défini (ou imprévisible) ou il causera les parties supplémentaires de la variable omise?
  3. Comment fonctionne le moulage de long à int en Do?
  4. comment la cession de long à int fonctionne en C quand je ne utilisez un casting?
53
demandé sur Community 2012-12-01 00:19:40

2 réponses

la langue garantit que int est au moins 16 bits, long est au moins 32 bits, et long peut représenter au moins toutes les valeurs que int peut représenter.

si vous assignez une valeur long à un objet int , elle sera convertie implicitement. Il n'y a pas besoin d'une distribution explicite; elle spécifierait simplement la même conversion qui va se produire de toute façon.

sur votre système, où int et long ont la même taille et la même portée, la conversion est triviale; elle copie simplement la valeur.

sur un système où long est plus large que int , si la valeur ne rentre pas dans un int , alors le résultat de la conversion est défini par implémentation. (Ou, à partir de C99, il peut émettre un signal défini par la mise en œuvre, mais je ne connais aucun compilateur qui le fasse réellement.) Quel typiquement se produit est que les bits de haut-ordre sont éliminés, mais vous ne devriez pas dépendre de cela. (Les règles sont différentes pour les types non signés; le résultat de la conversion d'un entier signé ou non signé en un type non signé est bien défini.)

si vous avez besoin de en toute sécurité Assignez une valeur long à un objet int , vous pouvez vérifier qu'il conviendra avant de faire la cession:

#include <limits.h> /* for INT_MIN, INT_MAX */

/* ... */

int i;
long li = /* whatever */

if (li >= INT_MIN && li <= INT_MAX) {
    i = li;
}
else {
    /* do something else? */
}

Les détails de "quelque chose d'autre" sont va dépendre de ce que vous voulez faire.

Une correction: int et long sont toujours types distincts, même s'ils ont la même taille et de la représentation. Les types arithmétiques sont librement convertibles, donc souvent cela ne fait aucune différence, mais par exemple int* et long* sont des types distincts et incompatibles; vous ne pouvez pas assigner un long* à un int* , ou vice versa, sans moulage explicite (et potentiellement dangereux).

et si vous devez convertir une valeur long en int , la première chose que vous devez faire est de reconsidérer la conception de votre code. Parfois de telles conversions sont nécessaires, mais le plus souvent elles sont un signe que le int auquel vous assignez aurait dû être défini comme un long en premier lieu.

42
répondu Keith Thompson 2015-04-12 18:22:30

Un long peut toujours représenter toutes les valeurs de int . Si la valeur présente peut être représentée par le type de la variable à laquelle vous assignez, alors la valeur est conservée.

si elle ne peut pas être représentée, alors pour le type de destination signé le résultat est formellement non spécifié, tandis que pour le type de destination non signé il est spécifié comme la valeur originale modulo 2 n , où n est le nombre de bits dans la représentation de la valeur (qui n'est pas nécessairement tous les bits dans la destination).

dans la pratique, sur les machines modernes vous obtenez l'emballage aussi pour les types signés.

c'est parce que les machines modernes utilisent la forme de complément de deux pour représenter des entiers signés, sans aucun bits utilisé pour dénoter" valeur invalide " ou tel – c.-à-d., tous les bits utilisés pour la représentation de valeur.

avec n représentation de la valeur en bits toute valeur entière est x correspond à x +K*2 n avec la constante entière K choisie de sorte que le résultat se situe dans l'intervalle où la moitié des valeurs possibles sont négatives.

ainsi, par exemple, avec 32 bits int la valeur -7 est représentée par un nombre bitpattern -7+2 32 = 2 32 -7, donc que si vous affichez le nombre que le bitpattern représente comme entier non signé, vous obtenez un nombre assez grand.

la raison pour laquelle cela est appelé complément de deux est parce qu'il a du sens pour le système de numération binaire, le système de numération de base deux. Pour le système de numération binaire il y a aussi un " (notez l'emplacement de l'apostrophe) en complément. De même, pour le système décimal, il y a le complément de ten et le complément de niners. Avec la représentation du complément de ten à 4 chiffres, vous représenteriez -7 comme 10000-7 = 9993. C'est tout, vraiment.

4
répondu Cheers and hth. - Alf 2012-11-30 20:36:56