Мне интересны кастинг между указателями на потенциально совместимые структуры. Они будут использовать один и тот же тег, те же элементы в том же порядке. Хотя целевая кодовая база скомпилирована как C или С++, для упрощения этого вопроса я хотел бы ограничить это только на С++.
Это ситуация, когда я уверен, что компилятор будет вести себя разумно, но я не могу найти подтверждающие доказательства того, что это необходимо для этого.
Пример мотивирующего кода:
#include <cstdio>
void foo(void * arg)
{
struct example
{
int a;
const char * b;
};
example * myarg = static_cast<example *>(arg);
printf("meaning of %s is %d\n",myarg->b,myarg->a);
}
void bar(void)
{
struct example
{
int a;
const char * b;
};
example on_stack {42, "life"};
foo(&on_stack);
}
int main(int,char**)
{
bar();
}
Мне не повезло со стандартом С++ 11. В разделе 9 по классам предполагается, что примеры будут "совместимы с макетами", что звучит обнадеживающе, но я не могу найти описание последствий того, что структуры "совместимы с макетами". В частности, могу ли я наложить указатель на один на указатель другого без последствий?
По мнению коллеги, "совместимость с макетами" означает, что memcpy будет работать так, как ожидалось. Учитывая, что рассматриваемая структура также всегда тривиально копируема, возможно, что следующий номинально неэффективный код избежит UB:
#include <cstdio>
#include <cstring>
void foo(void * arg)
{
struct example
{
int a;
const char * b;
};
example local;
std::memcpy(&local, arg, sizeof(example));
printf("meaning of %s is %d\n", local.b, local.a);
}
// bar and main as before
Фактическая мотивация для этого состоит в том, чтобы получить определение структуры из глобальной области, когда оно используется только для связи между небольшим количеством функций. Я понимаю, что это спорно, является ли это хорошая идея.