web-dev-qa-db-fra.com

Nombres négatifs décalés vers la droite en C

J'ai du code C dans lequel je fais ce qui suit.

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

Maintenant quand j'essaye

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

Autrement dit, -32767,5 est arrondi à -32768.

Cette compréhension est-elle correcte?

25
Alphaneo

Non, vous n'obtenez pas de nombres fractionnaires comme 0,5 lorsque vous travaillez avec des 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écalant d'un bit vers la droite et s'étendant vers la gauche (notez que cela dépend de l'implémentation, merci Trent):

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

Reconvertir en décimal:

 65535 >> 1 = 32767
-65535 >> 1 = -32768
18
Mark Byers

La spécification C ne spécifie pas si le bit de signe est décalé ou non. Cela dépend de la mise en œuvre.

7
Trent

Lorsque vous déplacez vers la droite, le bit le moins significatif est ignoré.

0xFFFF = 0 1111 1111 1111 1111, qui décale vers la droite pour donner 0 0111 1111 1111 1111 = 0x7FFF

-0xFFFF = 1 0000 0000 0000 0001 (complément de 2s), qui passe à 1 1000 0000 0000 0000 = -0x8000

3
Anon.

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

R-2: Le changement n'est pas la même chose que la division. C'est un décalage de bits - une opération binaire primitive. Qu'il puisse parfois être utilisé pour certains types de division est pratique, mais pas toujours le même.

3
wallyk

Sous le niveau C, les machines ont un cœur de processeur entièrement entier ou scalaire . Bien que de nos jours, chaque CPU de bureau dispose d'un FPU, ce n'était pas toujours le cas et même aujourd'hui, les systèmes embarqués sont fabriqués sans instructions en virgule flottante.

Les paradigmes de programmation, les conceptions de CPU et les langages actuels datent de l'époque où le FPU pourrait même ne pas exister.

Ainsi, les instructions du processeur implémentent des opérations en virgule fixe , généralement traitées comme purement entier ops. Ce n'est que si un programme déclare des éléments de float ou double qu'il y aura des fractions . (Eh bien, vous pouvez utiliser les opérations du processeur pour "point fixe" avec des fractions, mais c'est maintenant et toujours assez rare.)

Indépendamment de ce qui était exigé par un comité de normalisation linguistique il y a des années, toutes les machines raisonnables propagent le bit de signe sur les décalages droits des nombres signés. Les décalages vers la droite des valeurs non signées se décalent en zéros sur la gauche. Les bits décalés à droite sont déposés sur le sol.

Pour approfondir votre compréhension, vous devrez étudier "arithmétique à complément double".

2
DigitalRoss