struct foo_t { int val; };
struct bar_t { int val; };
struct container
{
foo_t foo;
bar_t bar;
};
void func(bar_t* b)
{
std::uintptr_t addr_of_b = reinterpret_cast(b);
// get address of foo
addr_of_b -= offsetof(container, bar);
foo_t* f = reinterpret_cast(addr_of_b);
// access f
f->val = 42;
}
Из cppreference (reinterpret_cast) я нашел эти две цитаты, которые кажутся в некоторой степени применимыми в этом сценарии. Однако в пункте 3) не говорится о случае, когда я изменяю целочисленное значение, а пункт 6), похоже, касается доступа к foo_t* непосредственно с адреса bar_t*. Определен ли где-нибудь вышеупомянутый сценарий?
Значение любого целочисленного или перечислимого типа можно преобразовать в тип указателя. Указатель, преобразованный в целое число достаточного размера и обратно в тот же тип указателя, гарантированно будет иметь исходное значение, в противном случае результирующий указатель не может быть безопасно разыменован (обратное преобразование в обратном направлении не гарантируется; тот же указатель может быть иметь несколько целочисленных представлений)
Выражение glvalue типа T1 можно преобразовать в ссылку на другое тип Т2. Результатом является результат *reinterpret_cast(p), где p — это указатель типа «указатель на T1» на объект или функцию, обозначенную выражением. Никакие временные объекты не создаются, не копируются, не вызываются конструкторы или функции преобразования. Безопасный доступ к полученной ссылке возможен только в том случае, если она доступна по типу.
Можно ли мне сделать это безопасно, если предположить, что func вызывается только с помощью &container_instance.bar? [code] struct foo_t { int val; }; struct bar_t { int val; };
struct container { foo_t foo; bar_t bar; };
void func(bar_t* b) { std::uintptr_t addr_of_b = reinterpret_cast(b); // get address of foo addr_of_b -= offsetof(container, bar); foo_t* f = reinterpret_cast(addr_of_b);
// access f f->val = 42; } [/code] Из cppreference (reinterpret_cast) я нашел эти две цитаты, которые кажутся в некоторой степени применимыми в этом сценарии. Однако в пункте 3) не говорится о случае, когда я изменяю целочисленное значение, а пункт 6), похоже, касается доступа к foo_t* непосредственно с адреса bar_t*. Определен ли где-нибудь вышеупомянутый сценарий?
[list] [*]Значение любого целочисленного или перечислимого типа можно преобразовать в тип указателя. Указатель, преобразованный в целое число достаточного размера и обратно в тот же тип указателя, гарантированно будет иметь исходное значение, в противном случае результирующий указатель не может быть безопасно разыменован (обратное преобразование в обратном направлении не гарантируется; тот же указатель может быть иметь несколько целочисленных представлений) [/list]
[list] [*]Выражение glvalue типа T1 можно преобразовать в ссылку на другое тип Т2. Результатом является результат *reinterpret_cast(p), где p — это указатель типа «указатель на T1» на объект или функцию, обозначенную выражением. Никакие временные объекты не создаются, не копируются, не вызываются конструкторы или функции преобразования. Безопасный доступ к полученной ссылке возможен только в том случае, если она доступна по типу. [/list]