Parce que je pense que c'est vraiment nécessaire, je veux simplement énoncer quelques règles de C et C++ (elles sont les mêmes à cet égard). Tout d'abord, tous les bits de unsigned char
participent à la détermination de la valeur si un objet unsigned char. Deuxièmement, unsigned char
est explicitement déclaré unsigned.
Maintenant, j'ai eu une discussion avec quelqu'un sur ce qui se passe lorsque vous convertissez la valeur -1
de type int en unsigned char
. Il a refusé l'idée que le unsigned char
résultant a tous ses bits définis à 1, car il était préoccupé par la représentation du signe. Mais il n'avait pas à l'être. Il découle immédiatement de cette règle que la conversion fait ce qui est prévu:
Si le nouveau type est unsigned, la valeur est convertie en ajoutant ou soustrayant de manière répétée une unité de plus que la valeur maximale pouvant être représentée dans le nouveau type jusqu'à ce que la valeur soit dans la plage du nouveau type. (6.3.1.3p2
dans un brouillon de C99)
C'est une description mathématique. C++ le décrit en termes de calcul modulo, ce qui conduit à la même règle. Quoi qu'il en soit, ce qui n'est pas garanti, c'est que tous les bits dans l'entier -1
soient à un avant la conversion. Alors, que pouvons-nous dire pour affirmer que le unsigned char
résultant a tous ses bits de CHAR_BIT
réglés à 1?
- Tous les bits participent à la détermination de sa valeur - c'est-à-dire qu'aucun bit de remplissage n'apparaît dans l'objet.
- Ajouter une seule fois
UCHAR_MAX+1
à -1
donnera une valeur dans la plage, à savoir UCHAR_MAX
C'est suffisant, en fait! Donc chaque fois que vous voulez avoir un unsigned char
ayant tous ses bits à un, vous faites
unsigned char c = (unsigned char)-1;
Cela signifie également qu'une conversion ne se limite pas à la simple troncation des bits de plus fort poids. L'événement favorable pour le complément à deux est que c'est juste une troncation là, mais la même chose n'est pas nécessairement vraie pour d'autres représentations de signe.