Wat is het nut van intptr_t?

Ik weet dat het een integer-type is dat naar/van de aanwijzer kan worden gecast zonder gegevensverlies, maar waarom zou ik dit ooit willen doen? Welk voordeel heeft het hebben van een integer-type ten opzichte van void*voor het vasthouden van de aanwijzer en THE_REAL_TYPE*voor rekenkunde van de aanwijzer?

BEWERKEN
De vraag gemarkeerd als “reeds gesteld” geeft hier geen antwoord op. De vraag is of het gebruik van intptr_tals algemene vervanging voor void*een goed idee is, en de antwoorden lijken te zijn “gebruik geen intptr_t”, dus mijn vraag is nog steeds geldig: wat zou een goede use case zijn voor intptr_t?


Antwoord 1, autoriteit 100%

De belangrijkste reden is dat u geen bitsgewijze bewerking kunt uitvoeren op een void *, maar u kunt hetzelfde doen op een intptr_t.

Bij veel gelegenheden, waarbij u een bitsgewijze bewerking op een adres moet uitvoeren, kunt u intptr_tgebruiken.

Voor bitsgewijze bewerkingen is de beste aanpak echter om de unsignedtegenhanger te gebruiken, uintptr_t.

Zoals vermeld in het andere antwoorddoor @chux, pointervergelijking is een ander belangrijk aspect.

Ook FWIW, volgens de C11-standaard, §7.2.1.4,

Deze typen zijn optioneel.


Antwoord 2, autoriteit 52%

Er is ook een semantische overweging.

Een void*wordt verondersteld naar iets te verwijzen. Ondanks de moderne bruikbaarheid, is een aanwijzer geen geheugenadres. Oké, meestal/waarschijnlijk/altijd(!) bevat het er één, maar het is geen nummer. Het is een wijzer. Het verwijst naar een ding.

A intptr_tniet. Het is een integer-waarde, die veilig is om naar / van een aanwijzer te converteren, zodat u het voor antieke API’s kunt gebruiken, inpakken in een pthreadFunctie-argument, dergelijke.

Daarom kunt u meer cijfer en bitty-dingen doen op een intptr_tdan u kunt op een void*, en waarom u zelfdocumenteert door de juiste te gebruiken Type voor de taak.

Uiteindelijk, bijna alles kan een integer (onthoud, uw computer werkt op nummers!). Pointers hadden gehetspersonen. Maar het zijn dat niet. Het zijn aanwijzingen, omdat ze bedoeld zijn voor ander gebruik. En, theoretisch, kunnen ze iets anders zijn dan cijfers.


3, Autoriteit 31%

De uintptr_tTYPE is erg handig bij het schrijven van geheugenbeheercode. Die soort code wil met zijn klanten praten in termen van generieke wijzers (void*), maar doe intern alle soorten rekenkunde op adressen.

U kunt enkele van dezelfde dingen doen door te werken in termen van char *, maar niet alles, en het resultaat lijkt op pre-ansi c.

Niet alle geheugenbeheercode gebruikt uintptr_t– Als voorbeeld definieert de BSD-kernel-code een vm_offset_tmet vergelijkbare eigenschappen. Maar als u b.v. Een Debug Malloc-pakket, waarom uw eigen type uitvinden?

Het is ook handig als u %pbeschikbaar hebt in uw printf, en schrijft code die de integrale variabelen van de aanwijzer in Hex op verschillende architecturen moet afdrukken.

Ik vind intptr_tnogal handig, behalve mogelijk als een manierstation bij het gieten, om de dread-waarschuwing te vermijden over het veranderen van ondertekendheid en integer-grootte in dezelfde cast. (Draagbare code schrijven die doorgeeft -Wall -WerrorOp alle relevante architecturen kan een beetje een strijd zijn.)


Antwoord 4, autoriteit 24%

Wat is het nut van intptr_t?

Voorbeeld van gebruik: bestelling vergelijken.
Het vergelijken van aanwijzingen voor gelijkheid is geen probleem.
Andere vergelijkingsbewerkingen zoals >, <=kunnen UB zijn. C11dr §6.5.8/5 Relationele operatoren.
Dus converteer eerst naar intptr_t.

[Bewerken] Nieuw voorbeeld: Sorteer een array van pointers op pointerwaarde.

int ptr_cmp(const void *a, const void *b) {
  intptr_t ia = (intptr) (*((void **) a));
  intptr_t ib = (intptr) (*((void **) b));
  return (ia > ib) - (ia < ib);
}
void *a[N];
...
qsort(a, sizeof a/sizeof a[0], sizeof a[0], ptr_cmp);

[Voormalig voorbeeld]
Gebruiksvoorbeeld: Test of een aanwijzer uit een reeks aanwijzers bestaat.

#define N  10
char special[N][1];
// UB as testing order of pointer, not of the same array, is UB.
int test_special1(char *candidate) {
  return (candidate >= special[0]) && (candidate <= special[N-1]);
}
// OK - integer compare
int test_special2(char *candidate) {
  intptr_t ca = (intptr_t) candidate;
  intptr_t mn = (intptr_t) special[0];
  intptr_t mx = (intptr_t) special[N-1];
  return (ca >= mn) && (ca <= mx);
}

Zoals commentaar van @MM, heeft de bovenstaande code werkt mogelijk niet zoals bedoeld. Maar het is in ieder geval geen UB. – alleen niet-draagbare functionaliteit. Ik hoopte dit te gebruiken om dit probleemop te lossen.

Other episodes