7
votes

long long vs int multilication

Compte tenu de l'extrait suivant:

1
4
8
10000
-1486618624


0 commentaires

4 Réponses :


5
votes

Le problème est que la multiplication est int32 * int32, qui est effectuée en tant quet32 et le résultat est ensuite attribué à un INT64. Vous obtiendrez beaucoup le même effet avec double d = 3/2; , qui diviserait 3 par 2 à l'aide de la division entière et assigner 1,0 à d

Vous devez faire attention au type d'expression ou de subexpression chaque fois que cela peut être important. Cela nécessite de s'assurer que l'opération appropriée est calculée en tant que type approprié, telle que la coulée d'une des multiplicandes à INT64, ou (dans mon exemple) 3.0 / 2 ou (flotteur) 3/2 .


3 commentaires

Très bien mis. @azraiyle doit changer cette ligne à int64 f = (int64) d * e;


Désolé que je n'ai pas déclaré que je connais la solution ici. Ce que je suis intéressé, c'est pourquoi la multiplication est int32 * int32 dans le premier cas et non int 8 * int8. Même si la CPU ne prend en charge que la multiplication INT32, elle peut être renvoyée à un INT8 après la multiplication. Mais l'instruction IA32 imul fonctionne pour les enregistreurs 8 bits (Al, ...).


@azrayl: au moins en C90, c promouvé tous les opérandes arithmétiques à INT s'ils étaient de types plus petits. Un coup d'œil à la norme C99 suggère que ce n'est plus le cas, mais je ne suis pas vraiment sûr. Quel compilateur C utilisez-vous et, le cas échéant, avec quelles options?



2
votes

a * b est calculé comme un int, puis jeté sur le type de variable de réception (qui arrive tout simplement d'int)

d * e est calculé sous forme d'int, puis couler au type de variable de réception (qui vient d'être int64)

Si l'une des variables de type était plus grande qu'un INT (ou un point flottant), que ce type n'aurait été utilisé. Mais puisque tous les types utilisés dans les multiplies étaient int ou plus petits, des INT ont été utilisés.


0 commentaires

3
votes

Lire K & R (l'original). Toutes les opérations entier sont effectuées avec le type entier naturel à moins que cela implique des variables (ou sont coulées) à quelque chose de plus grand. Les opérations de caractère sont coulées sur 32 bits car c'est la taille naturelle de l'entier sur cette architecture. La multiplication des deux entiers 32 bits est effectuée en 32 bits car rien ne le jette à rien de plus grand (jusqu'à ce que vous l'attribuiez à la variable 64 bits, mais c'est trop tard). Si vous voulez que l'opération se produise dans 64 bits, jetez une ou deux contre 64 bits.

int64 f = (int64)d * e;


0 commentaires

7
votes

La norme C99 spécifie que les opérateurs binaires tels que * ne fonctionnent pas sur des types d'entiers inférieurs à int . Les expressions de ces types sont favorisées à int avant l'application de l'opérateur. Voir 6.3.1.4 Paragraphe 2 et les nombreuses occurrences des mots «Promotion entière». Mais ceci est un peu orthogonal pour les instructions de montage générées par le compilateur, qui opère sur int S, car il est plus rapide même lorsque le compilateur serait autorisé à calculer un résultat plus court (car le résultat est immédiatement stocké dans une valeur L d'un type court, par exemple).

concernant int64 f = d * e; d et E sont de type int , la multiplication est fait comme un int conformément aux mêmes règles de promotion. Le débordement est techniquement comportement non défini , vous obtenez un résultat de deux-complément ici, mais vous pouvez obtenir n'importe quoi en fonction de la norme.

Remarque: les règles de promotion distinguent des types signés et non signés lors de la promotion. La règle est de promouvoir des types plus petits à int sauf si int ne peut pas représenter toutes les valeurs du type, auquel cas non signé INT est utilisé.


0 commentaires