Трюки с указателями в C / C ++ (сохранение указателя на int и перевод обратно) - PullRequest
3 голосов
/ 19 сентября 2011

Как говорит заголовок, в настоящее время я делаю небольшие хаки с указателями в C ++, но что-то не получается, вот что я получил:

uintptr_t texture_pointer = (int)((void*) &texture);

Где текстура это класс; похоже, это работает нормально, так как я получаю значение указателя, и я заверил, что я получаю то же значение в другую мою функцию, которая должна вернуть объект; это код, который не работает:

std::cout << "C++ BEFORE: " << texture_pointer << std::endl;
Texture texture = *(Texture*)((void*) texture_pointer);
std::cout << "C++ AFTER: " << (uintptr_t)((void*) &texture) << std::endl;

Вывод, который я исключал; было то, что одно и то же число для обоих, однако я получаю два разных числа, поэтому я думаю, что должна быть ошибка, но я не могу ее найти.

Пример вывода:

C++ BEFORE: 2685236
C++ AFTER: 2684960

Ответы [ 6 ]

9 голосов
/ 19 сентября 2011

Эта строка:

Texture texture = *(Texture*)((void*) texture_pointer);

создает новый Texture объект как копию исходного. Очевидно, что это адрес, отличный от старого.

Вы можете сделать это:

Texture &texture = *(Texture*)((void*) texture_pointer);

(т.е. создать ссылку на старую).

Но в общем, возиться с указателями, как это, больше проблем, чем стоит.

4 голосов
/ 19 сентября 2011

Для приведения к указателям на пустоту и из них используйте static_cast.Для приведения к и из целых чисел используйте reinterpret_cast:

SomeType* p;

// Make sure the type can hold a pointer.
std::uint64_t i = reinterpret_cast<std::uint64_t>(p);

...

SomeType* q = reinterpret_cast<SomeType*>(i); // Guaranteed to yield p back
1 голос
/ 19 сентября 2011

Как и ошибки, указанные уже в других ответах, эта строка неверна и вполне может дать сбой в 64-битных системах (LP64):

uintptr_t texture_pointer = (int)((void*) &texture);

Должно быть:

uintptr_t texture_pointer = (uintptr_t)&texture;

(если по какой-то причине вы хотите использовать приведение в стиле C, а не правильное приведение C ++).

0 голосов
/ 19 сентября 2011
Texture texture = *(Texture*)((void*) texture_pointer);

Эта строка создает новый объект и присваивает ему объект, на который указывает texture_pointer.Это отличается от создания указателя и его наведения на объект.Когда вы назначаете один объект другому, вы в основном копируете содержимое старого в новый.Поэтому имеет смысл, что два напечатанных адреса различны - это адреса двух разных объектов.

0 голосов
/ 19 сентября 2011

Если я правильно посчитал '*' в этой строке

Texture texture = *(Texture*)((void*) texture_pointer);

создает копию всех указателей на texture_pointer.

Итак, texture и * texture_pointer - это разные места хранения, поэтому & texture и texture_pointer имеют разные значения.

0 голосов
/ 19 сентября 2011

Изначально вы берете адрес объекта, размещенного в стеке, а не в куче.Строка:

Texture texture = *(Texture*)((void*) texture_pointer);

затем копирует этот объект в другой объект, размещенный в стеке.Затем вы берете адрес второго адреса.

Поскольку вы имеете дело с двумя разными объектами, у вас есть два разных адреса.

...