La norme C garantit que size_t
est un type qui peut contenir n'importe quel indice de tableau. Cela signifie que, logiquement, size_t
doit pouvoir contenir n'importe quel type de pointeur. J'ai lu sur certains sites que j'ai trouvés sur Google que cela est légal et/ou devrait toujours fonctionner :
void *v = malloc(10);
size_t s = (size_t) v;
Ainsi, en C99, la norme a introduit la fonction intptr_t
et uintptr_t
qui sont des types signés et non signés dont la capacité à contenir des pointeurs est garantie :
uintptr_t p = (size_t) v;
Alors quelle est la différence entre utiliser size_t
et uintptr_t
? Les deux sont non signés, et les deux devraient pouvoir contenir n'importe quel type de pointeur, donc ils semblent fonctionnellement identiques. Y a-t-il une raison impérieuse d'utiliser uintptr_t
(ou mieux encore, un void *
) plutôt qu'un size_t
à part la clarté ? Dans une structure opaque, où le champ ne sera traité que par des fonctions internes, y a-t-il une raison de ne pas le faire ?
Dans le même ordre d'idées, ptrdiff_t
a été un type signé capable de contenir des différences de pointeurs, et donc capable de contenir la plupart des pointeurs, alors comment se distingue-t-il de intptr_t
?
Tous ces types ne servent-ils pas essentiellement des versions trivialement différentes de la même fonction ? Si ce n'est pas le cas, pourquoi ? Qu'est-ce que je ne peux pas faire avec l'un d'eux que je ne peux pas faire avec un autre ? Si oui, pourquoi C99 a ajouté deux types essentiellement superflus au langage ?
Je suis prêt à ne pas tenir compte des pointeurs de fonction, car ils ne s'appliquent pas au problème actuel, mais n'hésitez pas à les mentionner, car je soupçonne qu'ils seront essentiels à la "bonne" réponse.