Conversion d’entiers (casting explicite et implicite)

J’ai regardé autour de moi et n’ai trouvé que des posts plus compliqués contenant des pointeurs. J’apprends le C et je voulais juste confirmer ma compréhension de quelques exemples. (Ces exemples supposent des tailles int et short int de 32 et 16 bits, respectivement.)

Code initial:

int int1 = 70000; int int2; short int shortInt1 = -70; short int shortInt2, shortInt3; 

Et quelques exemples de conversions:

 shortInt2 = int1 / shortInt1; 

Ma compréhension:
je. La division est effectuée (70000 / -70), donnant une valeur de -1000
ii. Comme int a une priorité plus élevée que short int, le résultat est atsortingbué à un entier anonyme signé.
iii. Anonyme signé int est converti en un court métrage anonyme signé
iv. La valeur du raccourci anonyme signé est assignée à shortInt2
v. Les entiers anonymes et entiers anonymes signés sont collectés
vi. Résultat: -1000

 shortInt3 = (short) int1 / shortInt1; 

Ma compréhension:
je. Dans la mesure où la conversion a priorité sur l’arithmétique, int1 est convertie en un short anonyme signé. Un débordement se produit, lui donnant une valeur de 4464
ii. La division est effectuée et le résultat de -63 est atsortingbué à un deuxième court métrage anonyme signé.
iii. La valeur du deuxième entier court anonyme signé est atsortingbuée à shortInt3
iv. Les deux in-court anonymes signés sont collectés
v. Résultat: -63

 int2 = (short)(int1 / shortInt2); 

C’est l’exemple par lequel je suis le plus confus. Je comprends que le casting a la priorité sur l’arithmétique, mais ici, il semble que les parenthèses entourant l’arithmétique donnent la priorité à l’arithmétique par rapport au casting. (Ce qui, je suppose, est logique, car l’opération de casting nécessite une certaine valeur pour le casting.)

Donc, ma compréhension:
je. La division est effectuée et, comme int a une priorité plus élevée, la valeur de la division est atsortingbuée à un entier anonyme signé.
ii. La signature anonyme anonyme est convertie en un short signé anonyme
iii. Le décalage vers la droite arithmétique est effectué sur le short int signé anonymement, ce qui le développe dans un autre
iv. La valeur de la deuxième signature anonyme anonyme est affectée à int2
v. Les entiers anonymes signés (le premier), anonymes signés short int et anonymes signés (le second) sont nettoyés
vi. Valeur: -1000

Votre question repose sur un certain nombre d’hypothèses incorrectes et utilise une terminologie incorrecte. Je commencerai par expliquer ce que dit le standard C à propos de votre exemple de code.

Vous pouvez obtenir une copie du dernier projet de la norme C, N1570 . Les “conversions arithmétiques habituelles” sont décrites dans la section 6.3.1.8; les promotions d’entiers sont décrites en 6.3.1.1.

 int int1 = 70000; 

Compte tenu de vos hypothèses, int est de 32 bits, il est donc assez gros pour contenir la valeur 70000 . (Il existe des systèmes où int ne fait que 16 bits; sur de tels systèmes, cela donnerait un résultat défini par l’implémentation.)

 int int2; short int shortInt1 = -70; 

70 est une constante de type int . L’opérateur unaire est appliqué à la valeur résultante, ce qui donne une valeur int de -70. L’initialisation entraîne la conversion de cette valeur int en type de l’object cible. Les conversions préservent les valeurs chaque fois que cela est possible et, étant donné que short largeur minimale de 16 bits, shortInt1 est défini sur la valeur évidente.

 short int shortInt2, shortInt3; shortInt2 = int1 / shortInt1; 

L’opérateur de division applique les conversions arithmétiques habituelles à ses deux opérandes. Il s’agit d’un ensemble de règles moyennement compliqué, conçu pour garantir que les deux opérandes sont du même type (la plupart du temps, C n’a pas d’opérateurs arithmétiques de type mixte). Ce cas est assez simple: l’opérande short int est converti en int , et le / est ensuite appliqué à deux opérandes int et produit un résultat int . La valeur est -1000 .

L’affectation provoque ensuite la conversion de ce résultat de int en short . Encore une fois, short est assez grand pour contenir cette valeur, donc shortInt2 obtient la valeur -1000 (de type short , pas int ).

La plupart des expressions en C sont évaluées sans tenir compte du contexte dans lequel elles apparaissent. Une division du côté droit d’une affectation n’est pas affectée par le type du côté gauche. Il est évalué séparément puis converti au type de cible si nécessaire.

 shortInt3 = (short) int1 / shortInt1; 

La conversion convertit la valeur de int1 en type short , l’opérateur / dispose donc de deux opérandes de type short . Mais les conversions arithmétiques habituelles sur les opérandes d’entier incluent les promotions d’entier , qui convertissent les deux opérandes short en un type int . La division int -by- int donne un résultat int , qui est ensuite converti en short et atsortingbué à shortInt3 .

 int2 = (short)(int1 / shortInt2); 

La division int1 / shortInt2 applique les conversions arithmétiques habituelles , qui convertissent l’opérande droit de short en int . Le résultat de la conversion int by- int est ensuite converti en short par la conversion. Le résultat short est ensuite converti en int car il est affecté à un object cible int .

Maintenant, pour éclaircir quelques points que vous avez écrits:

Comme int a une priorité plus élevée que short int, le résultat est atsortingbué à un entier anonyme signé.

Les types n’ont pas la priorité. Les opérateurs font. (Les types ont un rang , qui est utilisé pour déterminer les * conversions arithmétiques habituelles “.)

Vous semblez supposer que le résultat de l’évaluation d’une expression doit être affecté à un object (variable). Ce n’est pas le cas. L’évaluation d’une expression donne un résultat . Ce résultat est une valeur particulière, et est d’un type particulier, mais il n’a pas besoin d’être stocké nulle part. (Peut-être qu’il sera stocké temporairement dans un registre ou même dans un emplacement de mémoire, mais c’est un détail d’implémentation que nous pouvons ignorer en toute sécurité.) Il n’est pas nécessaire d’inventer un object “anonyme” pour conserver le résultat d’une expression. Le résultat est simplement. Finalement, il peut être stocké dans un object, transmis à une fonction ou utilisé en tant qu’opérande d’un autre opérateur. La manière dont cela est fait n’est pas définie par la norme C.