Estoy construyendo una estructura de datos de octárbol y, para ahorrar memoria para los nodos finales, me gustaría almacenar los valores directamente en el puntero en lugar de tener que crear un objeto hecho para contener 8 niños.

Mi tipo de datos es uint32_t, lo que significa que un puntero tiene suficientes bits para mantenerlo en x86 o amd64.

Entonces, ¿cómo almaceno un entero de 32 bits sin firmar en un puntero x86 o amd64?

Pseudocódigo:

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

¿Cómo es posible?

0
KaareZ 14 dic. 2016 a las 00:40

2 respuestas

La mejor respuesta

No se permite almacenar un entero sin signo directamente en un puntero de forma portátil, pero puede:

  • haga lo contrario: puede almacenar su puntero en un entero sin signo; específicamente, el estándar garantiza explícitamente que uintptr_t es lo suficientemente grande como para permitir que los punteros sobrevivan al viaje de ida y vuelta;
  • use un union:

    union NodePtr {
        Octree *child;
        uint32_t value;
    }
    

    aquí child y value comparten la misma ubicación de memoria, y se le permite leer sólo desde la última vez que escribió; cuando estás en un nodo terminal, usas value; de lo contrario, usa child.

5
Matteo Italia 13 dic. 2016 a las 21:48

Bueno, puede almacenar int como un puntero con conversiones:

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

Pero si lo hace de esta manera, no puedo ver cómo detecta que un Octree * determinado realmente almacena datos y no es un puntero a otro Octree

0
Dima Ogurtsov 13 dic. 2016 a las 21:50