web-dev-qa-db-fra.com

Les résultats des opérations au niveau du bit sur les entiers signés sont-ils définis?

Je sais que le comportement de >> sur un entier signé peut dépendre de l'implémentation (en particulier lorsque l'opérande de gauche est négatif).

Et les autres: ~, >>, &, ^, |? Lorsque leurs opérandes sont des entiers signés de type intégré (short, int, long, long long), les résultats sont-ils garantis identiques (en termes de contenu binaire) comme si leur type n'était pas signé?

44
updogliu

Pour les opérandes négatifs, << a un comportement indéfini et le résultat de >> est défini par l'implémentation (généralement comme décalage à droite "arithmétique"). << et >> ne sont pas conceptuellement des opérateurs au niveau du bit. Ce sont des opérateurs arithmétiques équivalents à la multiplication ou à la division par la puissance appropriée de deux pour les opérandes sur lesquels ils sont bien définis.

Quant aux véritables opérateurs au niveau du bit ^, ~, |, et &, ils opèrent sur la représentation binaire de la valeur dans le type (éventuellement promu) de l'opérande. Leurs résultats sont bien définis pour chaque choix possible de représentation signée (complément à deux, complément à un, ou amplitude du signe) mais dans les deux derniers cas, il est possible que le résultat soit une représentation piège si l'implémentation traite le "zéro négatif". représentation comme un piège. Personnellement, j'utilise presque toujours des expressions non signées avec des opérateurs au niveau du bit afin que le résultat soit 100% bien défini en termes de valeurs plutôt que représentations.

Enfin, notez que cette réponse telle qu'elle est écrite peut ne s'appliquer qu'à C. C et C++ sont des langages très différents et même si je ne connais pas bien C++, je comprends qu'elle peut différer dans certains de ces domaines de C ...

42
R..
  • Un décalage à gauche << d'une valeur négative a un comportement indéfini;
  • Un décalage à droite >> d'une valeur négative donne un résultat défini par l'implémentation;
  • Le résultat du &, | et ^ Les opérateurs sont définis en termes de représentation au niveau du bit des valeurs. Trois possibilités sont autorisées pour la représentation des nombres négatifs en C: complément à deux, complément à un et amplitude du signe. La méthode utilisée par l'implémentation déterminera le résultat numérique lorsque ces opérateurs seront utilisés sur des valeurs négatives.

Notez que la valeur avec le bit de signe 1 et tous les bits de valeur zéro (pour le complément à deux et l'amplitude du signe), ou avec le bit de signe et tous les bits de valeur 1 (pour le complément à un) est explicitement autorisée à être un représentation d'interruption, et dans ce cas, si vous utilisez des arguments pour ces opérateurs qui généreraient une telle valeur, le comportement n'est pas défini.

10
caf

Le contenu des bits sera le même, mais les valeurs résultantes dépendront toujours de l'implémentation.

Vous ne devriez vraiment pas voir les valeurs comme signées ou non signées lorsque vous utilisez des opérations au niveau du bit, car cela fonctionne à un niveau différent.

L'utilisation de types non signés vous évite certains de ces problèmes.

4
Bo Persson

La norme C89 définit le comportement des nombres signés décalés vers la gauche en fonction de la position des bits. Si ni les types signés ni non signés n'ont de bits de remplissage, le comportement requis pour les types non signés, combiné à l'exigence que les types signés positifs partagent la même représentation que les types non signés, impliquerait que le bit de signe se trouve immédiatement à gauche du bit de valeur le plus significatif .

Ceci, en C89, -1 << 1 serait -2 sur les implémentations à complément à deux qui n'ont pas de bits de remplissage et -3 sur les implémentations à complément à un qui n'ont pas de bits de remplissage. S'il existe des implémentations de grandeur de signe sans bits de remplissage, -1 << 1 serait égal à 2 sur celles-ci.

La norme C99 a changé les décalages à gauche des valeurs négatives en comportement indéfini, mais rien dans la justification ne donne la moindre idée de pourquoi (ou même mentionne le changement du tout). Le comportement requis par C89 peut avoir été moins qu'idéal dans certaines implémentations complémentaires, et il serait donc logique de laisser à ces implémentations la liberté de sélectionner quelque chose de mieux. Je n'ai vu aucune preuve suggérant que les auteurs de la norme ne voulaient pas que les implémentations de complément à deux de qualité continuent à fournir le même comportement exigé par C89, mais malheureusement, ils ne l'ont pas réellement dit.

2
supercat