J'utilise des ints non signés pour clarifier mon code et son intention. Une des choses que je fais pour me protéger contre les conversions implicites inattendues lorsque je fais du calcul avec des types signés et non signés consiste à utiliser un raccourci non signé (2 octets en général) pour mes variables non signées. Ceci est efficace pour plusieurs raisons:
- Lorsque vous faites de l'arithmétique avec vos variables courtes non signées et vos littéraux (de type int) ou vos variables de type int, cela garantit que la variable non signée sera toujours promue en un int avant d'évaluer l'expression, car int a toujours un rang supérieur à court. . Cela évite tout comportement inattendu en arithmétique avec les types signés et non signés, en supposant que le résultat de l'expression s'inscrit dans un int signé, bien sûr.
- La plupart du temps, les variables non signées que vous utilisez ne dépasseront pas la valeur maximale d'un raccourci non signé de 2 octets (65 535)
Le principe général est que le type de vos variables non signées doit avoir un rang inférieur à celui des variables signées afin de garantir la promotion du type signé. Vous n'aurez alors aucun comportement de débordement inattendu. Évidemment, vous ne pouvez pas vous en assurer tout le temps, mais (le plus), il est souvent faisable de le faire.
Par exemple, récemment, j'en ai eu quelques uns comme ceci:
const unsigned short cuint = 5;
for(unsigned short i=0; i<10; ++i)
{
if((i-2)%cuint == 0)
{
//Do something
}
}
Le littéral '2' est de type int. Si i était un unsigned int au lieu d'un unsigned short, alors, dans la sous-expression (i-2), 2 serait promu à un unsigned int (puisque unsigned int a une priorité plus élevée que signé). Si i = 0, la sous-expression est égale à (0u-2u) = une valeur massive due au débordement. Même idée avec i = 1. Cependant, comme i est un court non signé, il est promu au même type que le littéral '2', qui est signé int, et tout fonctionne bien.
Pour plus de sécurité: dans les rares cas où l'architecture que vous implémentez fait int en entier 2 octets, les deux opérandes de l'expression arithmétique peuvent être promus en unsigned int dans le cas où la variable courte unsigned ne correspond pas. dans le 2-byte int signé, ce dernier a une valeur maximale de 32 767 <65 535. (Voir https://stackoverflow.com/questions/17832815/c-implicit-conversion-signed-unsigned pour plus de détails). Pour vous protéger contre cela, vous pouvez simplement ajouter un static_assert à votre programme comme suit:
static_assert(sizeof(int) == 4, "int must be 4 bytes");
et il ne compilera pas sur les architectures où int est égal à 2 octets.
for(unsigned int n = 10; n >= 0; n --)
(boucles infiniment)