"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Pourquoi l'opérateur de décalage droit (`>>`) en C++ produit-il des résultats inattendus lors d'un décalage de 32 bits ?

Pourquoi l'opérateur de décalage droit (`>>`) en C++ produit-il des résultats inattendus lors d'un décalage de 32 bits ?

Publié le 2024-11-01
Parcourir:643

Why does the right shift operator (`>>`) en C produit des résultats inattendus lors d'un décalage de 32 bits ?
`) en C produisent des résultats inattendus lors d'un décalage de 32 bits ? " />

Comportement inattendu de l'opérateur de décalage vers la droite (1 >> 32)

Dans le domaine de la programmation, l'opérateur de décalage vers la droite (>>) est couramment utilisé pour effectuer des opérations au niveau du bit, en particulier pour diviser un entier par une puissance de deux. Cependant, un comportement particulier peut survenir lors du décalage par des valeurs plus grandes, comme le démontre le code C suivant :

int foo(int a, int b) {
   return a >> b;
}

int bar(uint64_t a, int b) {
   return a >> b;
}

int main() {
    std::cout > 32: " > 32) > (int)32: " > (int)32) 

Étonnamment, le résultat de ce programme révèle des résultats inattendus :

foo(1, 32): 1 // Should be 0
bar(1, 32): 0
1 >> 32: 0
(int)1 >> (int)32: 0

La justification de ces résultats réside dans le fonctionnement interne du processeur et du compilateur.

Comportement de la fonction foo()

Dans la fonction foo(), l'opération de décalage est effectuée sans transtypage, ce qui amène le CPU à effectuer un décalage logique vers la droite. Sur de nombreuses architectures, le décalage logique vers la droite est implémenté sous la forme a >> (b % 32), ignorant effectivement les bits supérieurs de b. Par conséquent, foo(1, 32) donne 1 >> (32 % 32), qui est évalué à 1 >> 0, ce qui donne 1.

Pourquoi la conversion en entier 64 bits est-elle importante ?

Dans la fonction bar(), un entier non signé de 64 bits est fourni, garantissant que le résultat est garanti 0 car b (32) est inférieur au nombre de bits de l'opérande (64 ). Cependant, lorsque b est modifié à 64, le résultat devient imprévisible et peut toujours donner 1.

Optimisation du compilateur

Dans le cas de 1 >> 32 et (int )1 >> (int)32, le compilateur optimise ces expressions constantes au moment de la compilation. La norme spécifie un comportement non défini pour les décalages vers la droite où le nombre est négatif ou supérieur ou égal à la longueur de l'opérande. Étant donné que 32 dépasse la longueur de l'opérande, le compilateur ne peut pas déterminer le résultat et génère 0 comme solution de repli sûre.

Comportement spécifique au processeur

L'implémentation du décalage à droite les opérations peuvent varier selon les différents processeurs. Sur les architectures x86/x86-64, le décalage logique vers la droite est effectivement a >> (b % 32 ou 64), selon le mode. Cependant, sur les processeurs ARM, l'opération de décalage à droite garantit zéro pour les décalages supérieurs ou égaux à 32.

Conclusion

Lorsque vous travaillez avec des opérateurs de décalage à droite, il est essentiel pour prendre en compte les comportements potentiels non définis, en particulier lorsque le nombre de décalages dépasse la longueur de l'opérande. La conversion vers des types entiers plus larges, tels que des entiers 64 bits, peut garantir des résultats cohérents sur différents processeurs et compilateurs.

Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3