Как бросить структуру C просто другой тип структуры, если их емкость памяти равна?

Я имею 2 матричных средства структур равные данные, но имею другую форму как они:

// Matrix type 1.
typedef float Scalar;
typedef struct { Scalar e[4]; } Vector;
typedef struct { Vector e[4]; } Matrix;

// Matrix type 2 (you may know this if you're iPhone developer)
// Defines CGFloat as float for simple description.
typedef float CGFloat;
struct CATransform3D
   {
   CGFloat m11, m12, m13, m14;
   CGFloat m21, m22, m23, m24;
   CGFloat m31, m32, m33, m34;
   CGFloat m41, m42, m43, m44;
};
typedef struct CATransform3D CATransform3D;

Их емкости памяти равны. Таким образом, я полагаю, что существует способ преобразовать эти типы без любых операций указателя или копии как это:

// Implemented in external lib.
CATransform3D CATransform3DMakeScale (CGFloat sx, CGFloat sy, CGFloat sz);
Matrix m = (Matrix)CATransform3DMakeScale ( 1, 2, 3 );

Действительно ли это возможно? В настоящее время компилятор печатает "ошибку: преобразование в нескалярный тип запросило" сообщение.

10
задан timrau 14 August 2012 в 23:52
поделиться

2 ответа

Вероятно, лучшим решением будет объединение двух структур в союз. Если вы хотите интерпретировать одни и те же данные двумя разными способами, то это очевидный выбор. Альтернативой является использование приведения указателей, но это некрасиво, нарушает правила алиасинга и может скрыть ошибки, о которых в противном случае компилятор мог бы сообщить.

typedef float Scalar;
typedef struct { Scalar e[4]; } Vector;
typedef struct { Vector e[4]; } Matrix;

struct CATransform3D
{
   CGFloat m11, m12, m13, m14;
   CGFloat m21, m22, m23, m24;
   CGFloat m31, m32, m33, m34;
   CGFloat m41, m42, m43, m44;
};
typedef struct CATransform3D CATransform3D;

typedef union
{
    CATransform3D t;
    Matrix m;
} UMatrix;

CATransform3D CATransform3DMakeScale (CGFloat sx, CGFloat sy, CGFloat sz);
UMatrix um;
um.t = CATransform3DMakeScale ( 1, 2, 3 );
//
// now you can just use um.m when you need to refer to the Matrix type...
//
16
ответ дан 3 December 2019 в 21:20
поделиться

Что ж, вы могли бы просто объявить CATransform3DMakeScale следующим образом:

Matrix CATransform3DMakeScale (CGFloat sx, CGFloat sy, CGFloat sz);

C не проверяет типы, чтобы убедиться, что ваше замедление соответствует исходной библиотеке. Если макет памяти такой же, он будет работать. Однако это плохая практика кодирования, и вы должны включить длинный комментарий, оправдывающий ваши действия. ; -)

Иначе не обойтись: придется использовать указатели или копировать данные. Это сработает:

CATransform3D m3d = CATransform3DMakeScale ( 1, 2, 3 );
Matrix m;
memcpy(&m, &m3d, sizeof m);

Как вы обнаружили, вы не можете создать структуру напрямую. Вы также не можете этого сделать:

Matrix m = *(Matrix*) &CATransform3DMakeScale ( 1, 2, 3 );

потому что C позволяет использовать оператор & только для l-значения.

1
ответ дан 3 December 2019 в 21:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: