Литье одной структуры С в другую

У меня есть две идентичные (но по-разному названные) структуры 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);
}