web-dev-qa-db-fra.com

Pouvez-vous contrôler ce qu'un décalage à droite au niveau du bit remplira C?

Pour autant que je sache, lorsque vous utilisez un opérateur de décalage à gauche dans C, il est garanti que les bits vacants seront remplis de 0. Cependant, j'ai lu que le bon décalage dépend de l'implémentation, ce qui signifie que dans certaines machines, les bits vacants seront remplis de 0, dans d'autres, ils seront remplis de 1.

J'utilise le bon décalage dans un programme, et en effet ma machine remplit les bits vacants avec 1s. Le problème est que j'en aurais besoin pour remplir avec 0 à la place.

Existe-t-il un moyen de forcer l'utilisation des 0 sur les bons décalages?

Une solution serait, après l'application du décalage à droite, de créer un masque comme 011111111, puis d'appliquer un ET au niveau du bit, ce qui changera le 1 le plus à gauche qui a été inséré en 0.

Mais cela est lourd et fait perdre du temps. S'il y avait un moyen de dire à ma machine de remplir les bons changements avec des 1, ce serait beaucoup plus facile.

Merci

28
Daniel Scocco

Convertissez le nombre en unsigned, puis déplacez. Cela forcera un remplissage à 0.

39
dan04

Non, tu ne peux pas.

Les décalages sur les types non signés sont bien définis (tant que l'opérande de droite est non négatif et inférieur à la largeur de l'opérande de gauche), et ils remplissent toujours zéro.

Les décalages (ou toute opération au niveau du bit) sur les types signés ne sont généralement pas une bonne idée. Si l'opérande gauche est négatif alors << a un comportement indéfini et >> donne un résultat défini par l'implémentation (ce qui signifie que le compilateur doit documenter ce qu'il fait, mais il n'y a aucun moyen pour vous de le contrôler). Pour les valeurs non négatives d'un type signé, le résultat est ce que vous attendez - tant qu'il ne déborde pas (s'il déborde, le comportement n'est pas défini).

Voici ce que dit le norme C99 (section 6.5.7):

Les promotions entières sont effectuées sur chacun des opérandes. Le type du résultat est celui de l'opérande gauche promu. Si la valeur de l'opérande droit est négative ou est supérieure ou égale à la largeur de l'opérande gauche promu, le comportement n'est pas défini.

Le résultat de E1 << E2 est E1 décalé vers la gauche E2 positions des bits; les bits libérés sont remplis de zéros. Si E1 a un type non signé, la valeur du résultat est E1 × 2 E2 , modulo réduit de plus de la valeur maximale représentable dans le type de résultat. Si E1 a un type signé et une valeur non négative, et E1 × 2 E2 est représentable dans le type de résultat, alors c'est la valeur résultante; sinon, le comportement n'est pas défini.

Le résultat de E1 >> E2 est E1 décalé vers la droite E2 positions des bits. Si E1 a un type non signé ou si E1 a 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.

17
Keith Thompson

Il existe deux opérations de décalage vers la droite différentes: arithmétique et logique.

Le décalage logique est utilisé avec des nombres non signés en C. Il remplit toujours les bits hauts avec des zéros. Voilà ce dont vous avez besoin.

Le décalage arithmétique est utilisé avec des nombres signés, car il préserve le signe du nombre en cours de décalage. Si le nombre est positif, le bit le plus significatif sera 0 et il se remplira de 0. Si le nombre est négatif, le bit le plus significatif sera 1, donc il se remplira de 1s.

Notez qu'en Java, ceux-ci utilisent en fait différents opérateurs: >> pour l'arithmétique, >>> pour logique. Ceci est nécessaire car Java n'a pas de type non signé.

5
Jay Conrod