Question

J'ai un code C dans que je ne le suit.

int nPosVal = +0xFFFF;   // + Added for ease of understanding
int nNegVal = -0xFFFF;   // - Added for valid reason

Maintenant, quand j'essaie

printf ("%d %d", nPosVal >> 1, nNegVal >> 1);

Je reçois

32767 -32768

Est-ce prévu?

Je suis capable de penser à quelque chose comme

65535 >> 1 = (int) 32767.5 = 32767
-65535 >> 1 = (int) -32767.5 = -32768

C'est, -32767.5 est arrondi à l'-32768.

Est-ce la compréhension correcte?

Était-ce utile?

La solution

Il semble que votre mise en œuvre fait probablement un décalage binaire arithmétique avec deux de nombres en complément. Dans ce système, il décale tous les bits à droite et remplit ensuite dans les bits supérieurs avec une copie de ce que le dernier bit était. Donc, pour votre exemple, le traitement int comme 32 bits ici:

nPosVal = 00000000000000001111111111111111
nNegVal = 11111111111111110000000000000001

Après le déplacement, vous avez:

nPosVal = 00000000000000000111111111111111
nNegVal = 11111111111111111000000000000000

Si vous convertissez ce retour en décimal, vous obtenez respectivement 32767 et -32768.

En effet, un décalage vers la droite complète vers l'infini négatif.

Modifier Selon la section 6.5.7 du dernier projet standard, ce comportement sur les nombres négatifs est mise en œuvre dépend:

Le résultat de E1 >> E2 est E1 positions de bits E2 décalé à droite. Si E1 est un type non signé ou si E1 est un type signé et une valeur non négative, la valeur du résultat est la partie intégrante du quotient de E1 / 2 E2 . Si E1 a un type signé et une valeur négative, la valeur résultante est définie par l'implémentation.

pour cela:

le Comité C89 a affirmé la liberté dans la mise en œuvre accordée par K & R en ne nécessitant pas l'opération de décalage vers la droite signé à signer étendre, étant donné qu'une telle exigence pourrait ralentir le code rapide et étant donné que l'utilité des signes quarts de travail prolongés est marginal. (Shifting complément à deux négatif entier arithmétiquement droite un endroit est pas la même chose que la division par deux!)

Il est donc mise en œuvre dépend en théorie. Dans la pratique, je ne l'ai jamais vu une implémentation pas faire un droit de décalage arithmétique lorsque l'opérande gauche est signé.

Autres conseils

Non, vous ne recevez pas des nombres fractionnaires comme 0,5 lorsque l'on travaille avec des nombres entiers. Les résultats peuvent être facilement expliqués lorsque vous regardez les représentations binaires des deux nombres:

      65535: 00000000000000001111111111111111
     -65535: 11111111111111110000000000000001

Bit décalage à droite un bit, et l'extension à gauche (notez que cette mise en œuvre dépend, grâce Trent):

 65535 >> 1: 00000000000000000111111111111111
-65535 >> 1: 11111111111111111000000000000000

reconvertir en décimal:

 65535 >> 1 = 32767
-65535 >> 1 = -32768

La spécification C ne précise pas si le bit de signe est décalé au-dessus ou non. Il dépend de l'implémentation.

Lorsque vous décalage vers la droite, le moins significatif bits est mis au rebut.

0xFFFF = 0 1111 1111 1111 1111, ce qui décalages à droite pour donner 0 0111 1111 1111 1111 = 0x7FFF

-0xFFFF = 1 0000 0000 0000 0001 (complément à 2), qui se déplace vers droite-1 1000 0000 0000 0000 = -0x8000

A-1:Oui.0xffff >> 1 est 0x7fff ou 32767.Je ne suis pas sûr de ce qu'-0xffff n'.C'est étrange.

A-2:Le déplacement est pas la même chose que de se diviser.C'est le décalage de bits—une primitive opération binaire.Qu'il peut parfois être utilisé pour certains types de division est pratique, mais pas toujours le même.

en dessous du niveau C, les machines ont un noyau d'unité centrale qui est entièrement entier ou scalaire . Bien que ces jours-ci tous les CPU de bureau a un FPU, cela n'a pas toujours été le cas et même les systèmes embarqués d'aujourd'hui sont faites sans instructions à virgule flottante.

Les paradigmes de programmation d'aujourd'hui et des conceptions CPU et les langues datent de l'époque où le FPU pourrait même pas exister.

Ainsi, les instructions CPU mettre en œuvre opérations en virgule fixe , généralement considérés comme purement entier ops. Seulement si un programme déclare éléments de float ou à double existera des fractions. (Eh bien, vous pouvez utiliser les opérations CPU pour « point fixe » avec des fractions, mais qui est maintenant et a toujours été assez rare.)

Peu importe ce qui a été requis par un il y a quelques années de comité de normalisation linguistique, toutes les machines raisonnables se propagent le bit de signe sur les décalages à droite des nombres signés. décale vers la droite des valeurs non signées changement dans des zéros sur la gauche. Les bits décalés sur la droite sont déposés sur le sol.

Pour approfondir votre compréhension, vous devrez enquêter sur "arithmétique complément à deux".

scroll top