У меня есть API с открытой структурой A и внутренней структурой B и должен иметь возможность преобразовать структуру B в структуру A. Является ли следующий код легальным и четко определенным поведением в C99 (и VS 2010/C89) и С++ 03/С++ 11? Если да, объясните, что делает его четким. Если это не так, то что является наиболее эффективным и кросс-платформенным средством для преобразования между двумя структурами?
struct A {
uint32_t x;
uint32_t y;
uint32_t z;
};
struct B {
uint32_t x;
uint32_t y;
uint32_t z;
uint64_t c;
};
union U {
struct A a;
struct B b;
};
int main(int argc, char* argv[]) {
U u;
u.b.x = 1;
u.b.y = 2;
u.b.z = 3;
u.b.c = 64;
/* Is it legal and well defined behavior when accessing the non-write member of a union in this case? */
DoSomething(u.a.x, u.a.y, u.a.z);
return 0;
}
UPDATE
Я упростил пример и написал два разных приложения. Один основан на memcpy, а другой - на объединении.
Союз:
struct A {
int x;
int y;
int z;
};
struct B {
int x;
int y;
int z;
long c;
};
union U {
struct A a;
struct B b;
};
int main(int argc, char* argv[]) {
U u;
u.b.x = 1;
u.b.y = 2;
u.b.z = 3;
u.b.c = 64;
const A* a = &u.a;
return 0;
}
тетср:
#include <string.h>
struct A {
int x;
int y;
int z;
};
struct B {
int x;
int y;
int z;
long c;
};
int main(int argc, char* argv[]) {
B b;
b.x = 1;
b.y = 2;
b.z = 3;
b.c = 64;
A a;
memcpy(&a, &b, sizeof(a));
return 0;
}
Профилированная сборка [DEBUG] (Xcode 6.4, компилятор С++ по умолчанию):
Вот соответствующая разница в сборке для режима отладки. Когда я профилировал сборки релизов, в сборке не было различий.
Союз:
movq %rcx, -48(%rbp)
тетср:
movq -40(%rbp), %rsi
movq %rsi, -56(%rbp)
movl -32(%rbp), %edi
movl %edi, -48(%rbp)
Оговорка:
Пример кода, основанного на объединении, вызывает предупреждение о том, что переменная 'a' не используется. Поскольку профилированная сборка отлаживается, я не знаю, есть ли какие-либо последствия.