À l'aide de intptr_t au lieu de void*?
Est-ce une bonne idée d'utiliser intptr_t
comme un usage général de stockage (pour contenir des pointeurs et des valeurs entières) au lieu de void*
? (Comme on le voit ici: http://www.crystalspace3d.org/docs/online/manual/Api1_005f0-64_002dBit-Portability-Changes.html)
Pour ce que j'ai déjà lu:
int
->void*
->int
aller-retour n'est pas garanti pour contenir la valeur d'origine; je suppose queint
->intptr_t
->int
fera- pointeur de l'arithmétique sur les deux
void*
etintptr_t
besoin de moulages, de sorte qu'aucun obtient l'avantage ici void*
signifie moins de conversions explicites lors de stocker des pointeurs,intptr_t
signifie moins de jette, lors du stockage des valeurs entièresintptr_t
nécessite C99
Quoi d'autre dois-je prendre en considération?
- Pas de. (Si c'était le cas, ils n'auraient qu'ajouté intptr_t de la sémantique à la
void*
) - Le poste demande "(pour contenir des pointeurs et des valeurs entières)", mais alors seulement explique
int
,void *
etintptr_t
. Commeuintmax_t
,size_t
,long long
, etc. sont également des types d'entiers, on dirait que la question est seulement sur les pointeurs d'objet,intptr_t
etint
types.
Vous devez vous connecter pour publier un commentaire.
Pas.
intptr_t
n'est pas garanti d'exister. Tout d'abord, comme vous le notez, il a été introduit en C99. Deuxièmement, les implémentations ne sont pas tenus d'avoir un type entier assez grand pour contenir converti en pointeur de valeurs, sans perte d'informations.De la conversion d'un
int
àintptr_t
et à l'arrière est peu probable de perdre de l'information, mais il n'y a aucune garantie queintptr_t
est plus large queint
.Si vous souhaitez stocker les valeurs de pointeur, de les stocker dans le pointeur objets. C'est ce pointeur objets sont pour.
Un pointeur vers un objet ou d'un type incomplète peut être converti
void*
et le dos encore une fois sans perte d'information. Il n'y a aucune garantie pour les pointeurs de fonctions, mais un pointeur de type de fonction peuvent être convertis à tout autre pointeur à la fonction-type et à l'arrière, sans perte d'informations. (Je fais référence à la norme C; je pense que POSIX offre quelques garanties supplémentaires.)Si vous souhaitez stocker un entier ou un pointeur de valeur dans le même objet, la première chose que vous devez faire est de repenser la conception de votre. Si vous avez déjà fait, et a conclu que vous n'avez vraiment envie de faire cela, pensez à utiliser un syndicat (et d'effectuer un suivi scrupuleux de ce type de valeur que vous avez enregistré le plus récemment).
Il y a des Api qui utilisent un
void*
argument pour permettre arbitraire données à transmettre; voir, par exemple, la POSIXpthread_create()
fonction. Cela peut être abusé par la coulée d'une valeur entière àvoid*
mais il est plus sûr de passer le adresse d'un objet integer.intptr_t
n'aller-retour d'un pointeur vers un le compare aussi - c'est que potentiellement pas la même séquence de bits de la perte de l'info de votre commentaire.intptr_t
est plus large queint
(même si je ne connais pas la mise en œuvre là où elle n'est pas). Si, par exemple,intptr_t
est 32 bits etint
est de 64 bits, la conversion d'unint
àintptr_t
et retour àint
pourrait perdre de l'information. Plus précisément, si leint
valeur est en dehors de la plage deintptr_t
, la première conversion des rendements de mise en œuvre définies par le résultat.intptr_t
et à l'arrière est peu probable de perdre d'info...". Mon commentaire était basé sur celui de la pensée. D'accord à propos de la rareté de laint/intptr_t
questions.Non, vous ne pouvez pas être garanti qu'un type particulier est une façon raisonnable de stocker à la fois les pointeurs et les nombres entiers, et d'ailleurs, il rend votre code source de confusion. Il ya une meilleure façon.
Si vous souhaitez stocker un entier et un pointeur sur l'objet même, le propre et portable méthode consiste à utiliser un syndicat:
Ce est portable et permet de stocker à la fois les sortes de choses dans la taille de l'espace de stockage nécessaire pour la plus grande des deux. Il est garanti pour toujours.
int
etvoid*
ont un tronc commun initial sous-suite en termes de mise en page? Sinon, c'est pas portable, vous êtes pas autorisé à stocker des deux membres à la fois et ce n'est absolument pas garanti "toujours travailler".;
après la définition de l'union.int
peuvent être stockées, et unvoid *
peuvent être stockées, mais il n'y a pas de suggestion de la simultanéité. NB. Il ne serait pas question siint
etvoid*
eu le même séquence initiale que cette règle ne s'applique qu'à des structures.