Установите значение указателя вручную

Я работаю в C. Я пытаюсь сделать функцию, которая будет возвращать int, содержащий адрес, указывающий на объект. Затем используйте полученный int (содержащий адрес) и создайте указатель, указывающий на этот адрес.

Пример:

MyClass* obj = SomeMethodReturningAPointerOfMyClass();
int address = (int) &obj;
return address;

Я думаю, что это работает для этой части. Значение, которое я получаю, составляет -4197276. (Может я совершенно не прав?)

Затем, с другой стороны, я хотел бы сделать что-то вроде:

MyClass* obj = (MyClass*) address;

который не работает, так как я не могу получить доступ к любому методу obj без получения ошибки.


Я нашел способ сделать это:

MyClass* obj = SomeMethodReturningAPointerOfMyClass();
machine->registers[2] = (int)obj;

затем в другом методе, где я получаю целое число, которое я сделал:

MyClass* obj = (MyClass*)address;

Я могу работать на объекте отлично! Может быть, не такой чистый, но он должен делать то, для чего он используется!

Спасибо всем, кто нашел время, чтобы ответить!

5 ответов

Во-первых, не делай этого. Вы получаете адрес указателя obj, а не объект, на который он указывает. obj уже равен этому адресу. &obj будет какое-то значение в стеке (в вашем случае, 0xFFBFF464) и он станет недействительным, когда ваша функция вернется.

Во-вторых, не делай этого. int это не тип C или C++ для адреса памяти - указатель есть, и он у вас уже есть.

int это не то же самое, что MyClass *, Фактически, в 64-битных системах (включая большинство современных ПК) приведение указателя к целому числу приводит к уменьшению половины значения указателя, и результат является недействительным.

Если вы хотите, чтобы ваша функция возвращала адрес объекта, верните указатель:

MyClass *GetAnObject(void) {
    MyClass *result = ...;
    return result;
}

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

Очевидно, поскольку вы используете классы, вы, вероятно, работаете в C++, а не в C.

Мне действительно интересно, почему вы на самом деле хотите хранить указатель на объект в int?

Относительно вашего вопроса: в зависимости от платформы указатель (объекта) может не помещаться в int. Если вы приведете указатель на int, вы можете просто обрезать значение указателя. Теперь, если вы вернётесь позже, указатель не будет завершён и укажет на какое-то неопределённое место в памяти. Это может вызвать проблемы.

Другими словами: не делай этого. Мало того, что вполне возможно, что он потерпит неудачу, это может даже вызвать много проблем.

&obj возвращает адрес где указатель obj хранится, что не совсем то, что вы хотите. Реальный ответ еще проще:

void *obj = SomeMethodReturningAPointerOfMyClass();
return (int) address;

Обратите внимание, что это сломается, если int не такой же размер, как указатель в вашей системе. Вы можете передать это как void *, intptr_t, или же long,

В зависимости от вашей системы, int может быть плохой выбор. Если вам действительно нужно передать указатель как целое значение, вы должны использовать uintptr_t который всегда гарантированно будет таким же большим, как указатель.

Также, &obj это, вероятно, не то, что вы хотите. Я думаю ты имел ввиду obj,

Прежде всего, вы должны использовать unsigned long введите вместо int, поскольку указатели имеют ширину 32 бита (по крайней мере, для 32-битной архитектуры; используйте unsigned long long если вы хотите быть в курсе 64-бит).

Далее, что вы храните в address переменная не является MyClass* но MyClass** как вы храните адрес объекта с помощью &obj при назначении address... (а также obj уже типа MyClass*)

Таким образом, вы должны либо хранить непосредственно MyClass* указатель, или если вы хотите сохранить указатель MyClass*а именно MyClass**, вам нужно сделать это дважды, используя еще одну '*', чтобы сбалансировать написанное вами "&" при address:

MyClass* obj = * ((MyClass*)address);
Другие вопросы по тегам