2016-12-13 9 views
0

Ich konstruiere eine Octree-Datenstruktur, und um Speicher für die endgültigen Knoten zu speichern, möchte ich die Werte direkt im Zeiger speichern, anstatt ein Objekt erstellen zu müssen, das 8 untergeordnete Elemente enthält .Speichern vorzeichenloser Ganzzahl in einem Zeiger

Mein Datentyp ist ein uint32_t was bedeutet, dass ein Zeiger genug Bits haben, um es entweder auf x86 oder amd64 zu halten.

Also wie speichere ich eine vorzeichenlose 32bit Integer in einem x86 oder amd64 Zeiger?

Pseudocode:

uint32_t i = 123; 
Octree* ptr = i; 
uint32_t ii = ptr; 
std::cout << ii << std::endl; //Prints 123 

Wie ist das möglich?

+0

uint32_t i = 123; Octree * ptr = reinterpret_cast (i); uint32_t ii = reinterpret_cast (ptr); – FamZ

+0

@FamZ: obwohl auf x86, das sollte funktionieren, es ist technisch illegal und * es gibt * einige bizarre Plattformen, wo dies zu einem Absturz führen würde (auch nur * Verweis * auf ungültige Zeiger löst Hardware-Ausnahmen auf diesen CPUs). –

Antwort

5

eine ganze Zahl ohne Vorzeichen Speicher gerade in ein Zeiger portably nicht erlaubt ist, aber man kann:

  • das Gegenteil tun: Sie Ihren Zeiger in einer ganzen Zahl ohne Vorzeichen speichern können; speziell wird uintptr_t explizit durch den Standard garantiert, groß genug zu sein, damit Zeiger den Roundtrip überleben können;
  • Verwendung ein union:

    union NodePtr { 
        Octree *child; 
        uint32_t value; 
    } 
    

    hier child und value die gleiche Speicherstelle, und Sie werden nur von dem einen lesen erlaubt, wo Sie das letzte Mal schrieb; Wenn Sie sich in einem Terminal-Knoten befinden, verwenden Sie value, andernfalls verwenden Sie child.

+0

Gibt es einen Overhead für die Verwendung von Union? Würde die obige Vereinigung den gleichen Platz wie ein roher Zeiger nehmen? – KaareZ

+0

@KaareZ: 'Gewerkschaften' sind praktisch frei auf jede anständige Implementierung - sie sind nur da, um dem Compiler zu sagen, dass Sie auf diesen Speicher mit mehreren Typen zugreifen werden, so dass die strengste Ausrichtungsanforderung gilt; Die Größe der Gewerkschaft ist "ausreichend, um die größten ihrer Datenmitglieder zu speichern" (und in der Praxis ist sie normalerweise so groß wie ihr größtes Mitglied). –

+0

Okay, dann ist das eine sehr gute Lösung, Sir. Vielen Dank. – KaareZ

0

Nun können Sie int als Zeiger mit Abgüssen speichern:

uint32_t i = 123; 
Octree* ptr = reinterpret_cast<Octree*>(i); 
uint32_t ii = reinterpret_cast<uint32_t>(ptr); 
std::cout << ii << std::endl; //Prints 123 

Aber wenn man es auf diese Weise tun Ich kann nicht sehen, wie Sie erkennen, dass ein gegebenes Octree * tatsächlich speichert Daten und ist kein Zeiger auf einen anderen Octree

+0

Ich hätte eine bool Flagge dafür. – KaareZ

+0

Wie oben erwähnt, obwohl dies auf x86 und anderen gebräuchlichen Architekturen funktioniert, ist es technisch nicht portierbar (Zeiger dürfen Trap-Repräsentationen haben). –

Verwandte Themen