Lorsqu'un int est converti en une courte et tronquée, quelle est la nouvelle valeur déterminée?
Quelqu'un peut-il clarifier ce qui se passe quand un nombre entier est converti en short
en C? Je suis en utilisant le Raspberry Pi, je suis conscient qu'un int
est de 32 bits, et donc un short
doit être de 16 bits.
Disons que j'utilise la suite du code C par exemple:
int x = 0x1248642;
short sx = (short)x;
int y = sx;
- Je obtenir x
serait tronquée, mais quelqu'un peut m'expliquer comment faire exactement? Sont des changements utilisé? Comment est exactement un certain nombre tronqué à partir de 32 bits à 16 bits?
- Notez que le plâtre (comme la plupart des plâtres) est inutile. Vous pouvez déclarer
short sx = x;
, et la valeur dex
sera converti implicitement enshort
. - La taille réelle de "int" et "court" varient et peuvent varier d'une plateforme à une autre. Mais oui, disons-le, "int" est de 32 bits et le "court" est de 16 bits: 1) Oui, le casting va tronquer la valeur de 32 à 16 bits, 2) Oui, les 16 bits supérieurs sont "perdus", 3) Non, il n'y a pas de touche "shift". PS: Saviez-vous que votre Raspberry Pi a probablement un à part entière de la copie de Mathematica? Certainement la peine de vérifier 🙂
- Pas exactement un doublon, mais étroitement liés: stackoverflow.com/q/19273658/4996248
- Aparté: vous pouvez supprimer largeur de bits de tâtonnement avec
#include <stdint.h>
à apporter dansint32_t
,int16_t
, etc.
Vous devez vous connecter pour publier un commentaire.
Selon la norme ISO C standard, lorsque vous convertir un entier de type signé, et la valeur est en dehors de la portée de la cible type, le résultat est la mise en œuvre définies. (Ou d'une mise en œuvre définies par le signal peut être soulevée, mais je ne sais pas du tout les compilateurs qui font cela.)
Dans la pratique, la plupart des communes de comportement est que les bits de poids fort sont mis au rebut. Donc en supposant
int
est 32 bits etshort
est de 16 bits, la conversion de la valeur0x1248642
sera probablement produire une séquence de bits qui ressemble à0x8642
. Et en supposant qu'un complément à deux de la représentation pour les types signés (qui est utilisé sur presque tous les systèmes), la haute-bit est le bit de signe, de sorte que la valeur numérique du résultat sera-31166
.Cela implique aussi une conversion implicite, de
short
àint
. Depuis la plage deint
est garanti pour couvrir l'ensemble de la gamme deshort
, la valeur est inchangée. (Depuis, dans votre exemple, la valeur desx
arrive à être négatif, ce changement de représentation est susceptible d'impliquer l'extension du signe, la multiplication de l'1
bit de signe à tous les 16 bits de poids fort du résultat.)Comme je l'ai indiqué, aucun de ces détails sont requis par la norme du langage. Si vous voulez vraiment tronquer les valeurs d'un rétrécissement de type, il est probablement préférable d'utiliser les types non signés (qui ont la langue spécifiée par l'enveloppant de comportement) et peut-être explicite les opérations de masquage, comme ceci:
Si vous avez une version 32 bits de la quantité que vous souhaitez pour s'engouffrer dans une 16-bits de la variable, la première chose que vous devez faire est de décider comment vous voulez que votre code se comporter si la valeur ne correspond pas. Une fois que vous avez décidé que, vous pouvez comprendre comment écrire le code C qui fait ce que vous voulez. Parfois, la troncature se trouve être ce que vous voulez, dans ce cas, votre tâche va être facile, surtout si vous utilisez des types non signés. Parfois, une plage de valeur est une erreur, dans ce cas, vous devez les vérifier et de décider comment gérer l'erreur. Parfois, vous voudrez peut-être la valeur de saturer, plutôt que de les tronquer, de sorte que vous aurez besoin d'écrire du code pour le faire.
De savoir comment les conversions en C est important, mais si vous commencer avec cette question, vous venez peut-être bientôt votre problème dans le mauvais sens.
x
va tenir dans une bref, au lieu de les masquer vous pouvezassert( x <= USHRT_MAX )
à faire appliquer cette hypothèse.x & 0xFFF
!=(short) x
siCHAR_BIT != 8
.CHAR_BIT * sizeof (short) != 16
. (J'ai travaillé sur des systèmes avecCHAR_BIT==8
oùsizeof (short)
est 4 ou même 8.Les 32 bits de valeur est tronquée à 16 bits dans la même façon un 32cm de long de pain à la banane serait réduit si vous la confiture dans une 16cm de long pan. La moitié des il serait bon et encore un pain à la banane, et le reste sera "disparu".
Troncature qui se passe dans les registres du CPU. Ces ont des tailles différentes: 8/16/32/64 bits. Maintenant, vous pouvez imaginer un registre comme:
x
est donné pour la première fois la valeur 32 bits0x1248642
. En mémoire*, ça va ressembler à:Maintenant, le compilateur charge
x
dans un registre. À partir de cela, il suffit de charger le moins significatif de 16 bits (à savoir,ax
) et de les stocker danssx
.*Boutisme n'est pas pris en compte pour des raisons de simplicité
Simplement les 16 bits sont coupés de l'entier. Par conséquent, votre court deviendra
0x8642
qui est en fait un nombre négatif-31166
.Peut-être laisser le code parle de lui-même:
De sortie:
Comme vous pouvez le voir,
int
->short
les rendements de la 16 bits de poids faible, comme prévu.Casting
short
àint
les rendements de lashort
avec les 16 bits élevés ensemble. Cependant, je suppose que c'est la mise en œuvre spécifique et un comportement indéfini. Vous êtes essentiellement de l'interprétation de 16 bits de la mémoire comme un entier, ce qui indique 16 bits supplémentaires de ce que les ordures qui se trouve là (ou 1 si le compilateur est agréable et veut vous aider à trouver les bugs plus rapidement).Je pense il doit être sûr pour effectuer les opérations suivantes:
Évidemment, vous n'obtiendrez pas revenir perdu bits, mais cela permettra de garantir que les bits élevés sont correctement mis à zéro.
Si quelqu'un peut vérifier le court -> int haute comportement des bits avec une référence, ce serait apprécié.
Note: Binaire macro adapté de cette réponse.
sx
valeur sera la même que 2 moins importante octets dex
, dans ce cas, il sera 0x8642 qui (si on l'interprète comme 16 bits entier signé) donne -31166 en décimal.0x8642
n'est pas-31166
en décimal.0x8642
est34370
en décimal. Cette valeur, si convertis pour une 16 bits signés type de produit typiquement-31166
, mais c'est une autre valeur.