Est-il important de déclarer une variable comme non signée si l'on sait qu'elle ne doit jamais être négative ? Cela permet-il d'éviter que des nombres autres que négatifs soient introduits dans une fonction qui ne devrait pas en avoir ?
Réponses
Trop de publicités?Mélanger des types signés et non signés peut être un véritable casse-tête. Le code qui en résulte est souvent gonflé, erroné, ou les deux(*). Dans la plupart des cas, à moins que vous n'ayez besoin de stocker des valeurs comprises entre 2 147 483 648 et 4 294 967 295 dans une variable 32 bits, ou que vous ayez besoin de travailler avec des valeurs supérieures à 9 223 372 036 854 775 807, je recommanderais de ne pas s'embarrasser de types non signés du tout.
(*) Ce qui devrait se passer, par exemple, si un programmeur fait.. :
{ Question would be applicable to C, Pascal, Basic, or any other language }
If SignedVar + UnsignedVar > OtherSignedVar Then DoSomething;
Je crois que l'ancien Pascal de Borland gérait le scénario ci-dessus en convertissant SignedVar et UnsignedVar en un type signé plus grand (le plus grand type pris en charge était signé, de sorte que chaque type non signé pouvait être converti en un type signé plus grand). Cela produirait un code volumineux, mais il serait correct. En C, si une variable signée est négative, le résultat sera probablement numériquement erroné, même si UnsignedVar contient zéro. Il existe également de nombreux autres mauvais scénarios.
Il y a deux choses principales à utiliser unsigned
vous donne
-
il permet d'utiliser la touche droite de la souris
>>
sur n'importe quelle valeur, puisqu'elle ne peut pas être négative -- l'utilisation d'un décalage vers la droite sur une valeur négative n'est pas définie. -
il permet d'obtenir une arithmétique mod 2^n enveloppante. Avec des valeurs signées, l'effet du sous-débit/surdébit n'est pas défini. Avec des valeurs non signées, vous obtenez une arithmétique mod 2^n, donc
0U - 1U
vous donnera toujours la plus grande valeur non signée possible (qui sera toujours inférieure de 1 à une puissance de 2).
Un contre-argument à l'utilisation de unsigned
est que vous pouvez vous retrouver dans des situations très raisonnables où cela devient gênant et où des bogues involontaires sont introduits. Considérons une classe - par exemple une classe de liste ou autre - avec la méthode suivante :
unsigned int length() { ... }
Cela semble très raisonnable. Mais lorsqu'on veut itérer dessus, on obtient ce qui suit :
for (unsigned int i = my_class.length(); i >= 0; --i) { ... }
Votre boucle ne se termine pas et vous êtes maintenant obligé de lancer ou de faire une autre maladresse.
Une alternative à l'utilisation de unsigned
est juste de assert
que vos valeurs sont non négatives.
Soit dit en passant, j'utilise rarement int
o unsigned int
Je préfère utiliser soit { int16_t
, int32_t
, ... } ou { uint16_t
, uint32_t
...}. (Vous devez inclure les éléments suivants stdint.h
de les utiliser). Je ne sais pas comment mes collègues trouvent cela, mais j'essaie de faire comprendre la taille de la variable de cette manière. À certains endroits, j'essaie d'être plus flagrant en faisant quelque chose comme : typedef uint32_t Counter32;
- Réponses précédentes
- Plus de réponses