Dans certains cas, vous devez utiliser unsigned integer types sont:
- Vous avez besoin pour traiter une donnée comme une pure représentation binaire.
- Vous avez besoin de la sémantique de l'arithmétique modulo vous obtenez avec des nombres non signés.
- Vous avez à l'interface avec le code qui utilise les types non signés (par exemple, la norme de la bibliothèque de routines qui acceptent/retour
size_t
valeurs.
Mais pour le général, l'arithmétique, la chose est, quand vous dites que quelque chose "ne peut pas être négatif," cela ne veut pas nécessairement dire que vous devez utiliser un type non signé. Parce que vous pouvez mettre une valeur négative dans un unsigned, c'est juste qu'il va devenir une très grande valeur quand vous allez sortir. Donc, si vous voulez dire que les valeurs négatives sont interdites, comme pour une base de la racine carrée de la fonction, alors vous êtes en indiquant une condition préalable de la fonction, et vous devriez le faire valoir. Et vous ne pouvez pas affirmer que ce qui ne peut l'être, est; vous avez besoin d'un moyen de tenir out-of-band valeurs de sorte que vous pouvez les tester (c'est le même genre de logique qui sous-tend getchar()
retourner un int
et pas char
.)
En outre, le choix de l'signé-vs-non signé peut avoir des répercussions sur la performance, ainsi. Jetez un oeil à l' (fictive) de code ci-dessous:
#include <stdbool.h>
bool foo_i(int a) {
return (a + 69) > a;
}
bool foo_u(unsigned int a)
{
return (a + 69u) > a;
}
Les deux foo
's sont les mêmes, sauf pour le type de leurs paramètres. Mais, lorsqu'il est compilé avec c99 -fomit-frame-pointer -O2 -S
, vous obtenez:
.fichier "essai.c"
.texte
.p2align 4,,15
.globl foo_i
.type foo_i, @fonction
foo_i:
movl $1, %eax
ret
.taille foo_i, .-foo_i
.p2align 4,,15
.globl foo_u
.type foo_u, @fonction
foo_u:
movl 4(%esp), %eax
leal 69(%eax), %edx
cmpl %eax, %edx
seta %al
ret
.taille foo_u, .-foo_u
.ident "GCC: (Debian 4.4.4-7) 4.4.4"
.de la section .remarque.GNU-de la pile",",@progbits
Vous pouvez voir qu' foo_i()
est plus efficace que l' foo_u()
. C'est parce que unsigned de dépassement de capacité arithmétique est défini par la norme afin d'envelopper autour de," ainsi (a + 69u)
peut très bien être plus petit que a
si a
est très grand, et donc il doit y avoir des code pour ce cas. D'autre part, signé de dépassement de capacité arithmétique est pas défini, donc GCC va aller de l'avant et d'assumer arithmétique signée n'a pas de débordement, et donc, (a + 69)
ne peut jamais être inférieur a
. Le choix de types non signés sans discernement peut donc limiter l'impact direct sur les performances.