Qu'est-ce que uintptr_t
et à quoi peut-il servir?
uintptr_t
est un type entier non signé capable de stocker un pointeur. Ce qui signifie généralement que sa taille est identique à celle d'un pointeur.
optionnellement défini dans les standards C++ 11 et ultérieurs.
Une raison courante de vouloir un type entier pouvant contenir le type de pointeur d'une architecture est d'effectuer des opérations spécifiques à un entier sur un pointeur ou de masquer le type d'un pointeur en le fournissant sous la forme d'un "handle" entier.
Edit: Notez que Steve Jessop a quelques détails supplémentaires très intéressants (que je ne volerai pas) dans une autre réponse ici pour vous types pédantiques:)
Première chose, au moment où la question a été posée, uintptr_t
n'était pas en C++. C'est en C99, dans <stdint.h>
, en tant que type facultatif. De nombreux compilateurs C++ 03 fournissent ce fichier. C'est également en C++ 11, dans <cstdint>
, où il est à nouveau facultatif et qui fait référence à C99 pour la définition.
En C99, il est défini comme "un type entier non signé avec la propriété selon laquelle tout pointeur valide sur void peut être converti en ce type, puis reconverti en pointeur à vide, et le résultat sera comparable au pointeur original".
Prenez cela pour signifier ce qu'il dit. Cela ne dit rien sur la taille.
uintptr_t
pourrait avoir la même taille qu'un void*
. Il pourrait être plus grand. Elle pourrait éventuellement être plus petite, bien qu'une telle implémentation en C++ soit une approche perverse. Par exemple, sur une plate-forme hypothétique où void*
est de 32 bits, mais où seulement 24 bits d'espace d'adressage virtuel sont utilisés, vous pouvez avoir un uintptr_t
de 24 bits qui satisfait à l'exigence. Je ne sais pas pourquoi une implémentation ferait cela, mais la norme le permet.
C'est un type entier non signé exactement de la taille d'un pointeur. Chaque fois que vous devez faire quelque chose d'inhabituel avec un pointeur - par exemple, inverser tous les bits (ne demandez pas pourquoi), vous le convertissez en uintptr_t
et le manipulez sous la forme d'un nombre entier habituel, puis le rejouez.
Il y a déjà beaucoup de bonnes réponses à la partie "quel est le type de données uintptr_t". Je vais essayer de répondre à la question "à quoi sert-il?" partie à ce post.
Principalement pour les opérations au niveau des bits sur les pointeurs. N'oubliez pas qu'en C++, vous ne pouvez pas effectuer d'opérations au niveau des bits sur les pointeurs. Pour des raisons, voyez Pourquoi ne pouvez-vous pas effectuer d'opérations au niveau des bits sur le pointeur en C, et existe-t-il un moyen de contourner ce problème?
Ainsi, pour pouvoir effectuer des opérations au niveau des bits sur les pointeurs, il faut les convertir en caractères unitpr_t, puis effectuer des opérations au niveau des bits.
Voici un exemple de fonction que je viens d’écrire pour faire une exclusivité au niveau du bit ou de 2 pointeurs à stocker dans une liste chaînée XOR afin que nous puissions parcourir dans les deux sens comme une liste doublement chaînée mais sans la pénalité de stocker 2 pointeurs dans chaque noeud.
template <typename T>
T* xor_ptrs(T* t1, T* t2)
{
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(t1)^reinterpret_cast<uintptr_t>(t2));
}