Есть указатель на член, нужно получить числовое представление этого адреса, иными словами смещение. В коде вот так:
struct Foo
{
int Bar;
};
auto pointer_to_member = &Foo::Bar;
auto offset_of_member = reinterpret_cast<uintptr_t>(pointer_to_member); // ошибка
Мой VisualC++ пишет ошибку:
error C2440: reinterpret_cast
cannot convert int Foo::Bar *
to uintptr_t
Вопросы. Это что не по стандарту? И как получить смещение без offsetof
так как в наличии уже готовый указатель на член?
MSVC прав, так делать нельзя.
Через offsetof тоже не получится, потому что он работает только с именами полей, а не с указателями на них.
На MSVC может сработать offsetof(Foo, *pointer_to_member)
из-за особенностей реализации этого самого offsetof
. Но это не сооветствует стандарту и не работает как минимум на GCC.
Единственный полностью стандартный способ (насколько я знаю) - это создать объект, применить к нему указатель на поле, и вычесть из адреса поля адрес объекта:
Foo foo;
std::cout << (char *)&(foo.*pointer_to_member) - (char*)&foo;
Более удобный вариант - это сделать type-punning из указателя на поле в uintptr_t
через memcpy()
:
static_assert(sizeof(pointer_to_member) == sizeof(uintptr_t));
uintptr_t offset;
std::memcpy(&offset, &pointer_to_member, sizeof offset);
std::cout << offset;
Стандарт не гарантирует (насколько я знаю, опять же), что указатель на поле хранится как смещение, но это должно сработать на всех основных компиляторах.
Если под рукой нет уже готовых объектов Foo
, я бы использовал именно этот способ.
Не стоит пробовать reinterpret_cast<uintptr_t &>(pointer_to_member)
, или type-punning через union
. И то, и другое - неопределенное поведение из-за нарушения strict aliasing.
Вот еще один способ. Выглядит удобно, но является неопределенным поведением из-за доступа по невалидному указателю.
(Хотя дефолтная реализация offsetof
в MSVC использует похожий трюк.)
std::cout << (uintptr_t)&((Foo *)(0)->*pointer_to_member);
Вашим способом нельзя. Открываем документацию на offsetof и читаем
offsetof cannot be implemented in standard C++ and requires compiler support
В gcc она сделана так
/* Offset of member MEMBER in a struct of type TYPE. */
#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
Это что не по стандарту?
Да, это преобразование не по стандарту. Для указателей на член операцию преобразования к целому не определена. По факту указатель на член не является «указателем» в классическом понимании слова.
И как получить смещение без offsetof так как в наличии уже готовый указатель на член?
Легально — ни как. Внутреннее устройство указателя на член определяется реализацией.
Не легально на большинстве систем можно сделать что-то такое, но это UB:
*(off_t*) &pointer_to_member
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Ранее пользовался Linux/Ubuntu и не было ни каких проблем с отладкой (использовался gcc + gdb)Сейчас перешел на MacOS и появилась большая проблема
Не могу понять в чём ошибка пробовал различные способы менял структуру нечего не помогает,после моих попыток я смог только задержать ошибку...
Подключаю кwar приложению JPA
Есть приложение с таблицей Не обновляется БД в андроид приложении, необходимо по нажатию кнопки менять размер шрифтаВ activity_main