Wat is het gegevenstype uintptr_t

Wat is uintptr_ten waarvoor kan het worden gebruikt?


Antwoord 1, autoriteit 100%

uintptr_tis een niet-ondertekend geheel getal dat een datapointer kan opslaan. Wat meestal betekent dat het even groot is als een aanwijzer.

Het is optioneel gedefinieerd in C++11 en latere normen.

Een veelvoorkomende reden om een integer type te willen dat het pointertype van een architectuur kan bevatten, is om integer-specifieke bewerkingen op een pointer uit te voeren, of om het type van een pointer te verdoezelen door het als een integer “handle” te geven.


Antwoord 2, autoriteit 98%

Ten eerste, op het moment dat de vraag werd gesteld, was uintptr_tniet in C++. Het staat in C99, in <stdint.h>, als een optioneel type. Veel C++03-compilers leveren dat bestand wel. Het staat ook in C++11, in <cstdint>, waar het opnieuw optioneel is, en dat verwijst naar C99 voor de definitie.

In C99 wordt het gedefinieerd als “een niet-ondertekend geheel getal met de eigenschap dat elke geldige aanwijzer naar void kan worden geconverteerd naar dit type en vervolgens terug kan worden geconverteerd naar aanwijzer naar void, en het resultaat zal gelijk zijn aan de originele aanwijzer” .

Neem dit om te betekenen wat het zegt. Het zegt niets over de maat.

uintptr_tkan even groot zijn als een void*. Het is misschien groter. Het zou denkbaar kleiner kunnen zijn, hoewel een dergelijke C++-implementatie pervers benadert. Bijvoorbeeld op een hypothetisch platform waar void*32 bits is, maar slechts 24 bits virtuele adresruimte wordt gebruikt, zou u een 24-bits uintptr_tkunnen hebben die voldoet aan de vereiste . Ik weet niet waarom een implementatie dat zou doen, maar de standaard staat het toe.


Antwoord 3, autoriteit 10%

Het is een niet-ondertekend geheel getal met precies de grootte van een aanwijzer. Wanneer je iets ongewoons moet doen met een aanwijzer – zoals bijvoorbeeld alle bits omkeren (vraag niet waarom), cast je het naar uintptr_ten manipuleert het als een gebruikelijk geheel getal, en cast je dan terug.


Antwoord 4, autoriteit 7%

Er zijn al veel goede antwoorden op het onderdeel “wat is uintptr_t datatype”. Ik zal proberen in te gaan op de vraag “waarvoor kan het worden gebruikt?” deel aan dit bericht.

Voornamelijk voor bitsgewijze bewerkingen op pointers. Onthoud dat men in C++ geen bitsgewijze bewerkingen op pointers kan uitvoeren. Zie voor redenen Waarom kun je geen bitsgewijze bewerkingen uitvoeren op de aanwijzer in C, en is er een manier om dit te omzeilen?

Dus om bitsgewijze bewerkingen op pointers uit te voeren, zou men pointers moeten casten om unitpr_t te typen en vervolgens bitsgewijze bewerkingen uitvoeren.

Hier is een voorbeeld van een functie die ik zojuist heb geschreven om bitsgewijze exclusief uit te voeren of van 2 pointers om op te slaan in een XOR-gekoppelde lijst, zodat we in beide richtingen kunnen gaan als een dubbel gelinkte lijst, maar zonder de straf van het opslaan van 2 pointers in elk knooppunt.

template <typename T>
 T* xor_ptrs(T* t1, T* t2)
 {
     return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(t1)^reinterpret_cast<uintptr_t>(t2));
  }

Antwoord 5, autoriteit 2%

Om het risico te lopen nog een Necromancer-badge te krijgen, zou ik graag een zeer goed gebruik willen toevoegen voor uintptr_t(of zelfs intptr_t) en dat is het schrijven van testbare embedded code.

Ik schrijf voornamelijk embedded code gericht op verschillende arm- en momenteel tensilica-processors. Deze hebben verschillende native busbreedtes en de tensilica is eigenlijk een Harvard-architectuur met afzonderlijke code- en databussen die verschillende breedtes kunnen hebben.

Ik gebruik een testgestuurde ontwikkelstijl voor veel van mijn code, wat betekent dat ik eenheidstests doe voor alle code-eenheden die ik schrijf. Het testen van eenheden op daadwerkelijke doelhardware is een gedoe, dus ik schrijf meestal alles op een Intel-pc in Windows of Linux met Ceedling en GCC.

Dat gezegd hebbende, veel ingebedde code omvat bit-twiddelen en adresmanipulaties. De meeste van mijn Intel-machines zijn 64-bits. Dus als je adresmanipulatiecode gaat testen, heb je een gegeneraliseerd object nodig om wiskunde op te doen. Dus de uintptr_tgeeft je een machine-onafhankelijke manier om je code te debuggen voordat je probeert te implementeren op doelhardware.

Een ander probleem is dat voor sommige machines of zelfs geheugenmodellen op sommige compilers, functieaanwijzers en gegevensaanwijzers verschillende breedtes hebben. Op die machines staat de compiler misschien niet eens casten tussen de twee klassen toe, maar uintptr_tzou dat wel moeten kunnen.

— Bewerken —

Werd erop gewezen door @chux, dit maakt geen deel uit van de standaard en functies zijn geen objecten in C. Het werkt echter meestal en aangezien veel mensen deze typen niet eens kennen, laat ik meestal een opmerking achter waarin ik de truc uitleg. Andere zoekopdrachten in SO op uintptr_tzullen verdere uitleg geven. We doen ook dingen bij het testen van eenheden die we nooit zouden doen in de productie, omdat dingen kapot maken goed is.

Other episodes