Литье одной структуры С в другую
У меня есть две идентичные (но по-разному названные) структуры C:
typedef struct {
double x;
double y;
double z;
} CMAcceleration;
typedef struct {
double x;
double y;
double z;
} Vector3d;
Теперь я хочу назначить переменную CMAcceleration переменной Vector3d (копирование всей структуры). Как я могу это сделать?
Я пробовал следующее, но получаю следующие ошибки компилятора:
vector = acceleration; // "incompatible type"
vector = (Vector3d)acceleration; // "conversion to non-scalar type requested"
Конечно, я могу прибегнуть к установке всех членов по отдельности:
vector.x = acceleration.x;
vector.y = acceleration.y;
vector.z = acceleration.z;
но это кажется неудобным.
Какое лучшее решение?
Ответы
Ответ 1
Это ваше единственное решение (кроме его включения в функцию):
vector.x = acceleration.x;
vector.y = acceleration.y;
vector.z = acceleration.z;
Фактически вы можете использовать его (используя указатели)
Vector3d *vector = (Vector3d*) &acceleration;
но это не в спецификациях, и поэтому поведение зависит от компилятора, времени выполнения и большого зеленого космического монстра.
Ответ 2
Вы можете использовать указатель, чтобы сделать typecast;
vector = *((Vector3d *) &acceleration);
Ответ 3
Почему вы не используете.
typedef CMAcceleration Vector3d;
(вместо создания целой новой структуры)
в этом случае vector = acceleration;
просто компилируется.
Ответ 4
Для этого используется служебная функция:
void AccelerationToVector( struct CMAcceleration* from, struct Vector3d* to )
{
to->x = from->x;
to->y = from ->y;
to->z = from->z;
}
Ответ 5
memcpy(&vector, &acceleration, sizeof(Vector3d));
Обратите внимание, что это работает только, если физический макет структур в памяти идентичен. Однако, как отметил @Oli, компилятор не обязан это гарантировать!
Ответ 6
Безопасный (хотя и несколько запутанный) способ сделать это - использовать союз:
union { CMAcceleration a, Vector3d v } tmp = { .a = acceleration };
vector = tmp.v;
Значения переинтерпретируются (начиная с C99), когда доступный элемент не является последним установленным. В этом случае мы устанавливаем ускорение, а затем получаем доступ к вектору, поэтому ускорение интерпретируется.
Таким образом реализуется функция NSRectToCGRect.
Ответ 7
Это достигается с помощью union:
typedef struct {
double x;
double y;
double z;
} CMAcceleration;
typedef struct {
double x;
double y;
double z;
} Vector3d;
typedef union {
CMAcceleration acceleration;
Vector3d vector;
} view;
int main() {
view v = (view) (Vector3d) {1.0, 2.0, 3.0};
CMAcceleration accel = v.acceleration;
printf("proof: %g %g %g\n", accel.x, accel.y, accel.z);
}