简体   繁体   English

如果内存大小相等,如何将C结构转换为另一种结构类型?

[英]How to cast C struct just another struct type if their memory size are equal?

I have 2 matrix structs means equal data but have different form like these: 我有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;

Their memory sizes are equal. 他们的记忆大小相等。 So I believe there is a way to convert these types without any pointer operations or copy like this: 所以我相信有一种方法可以转换这些类型,而无需任何指针操作或复制,如下所示:

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

Is this possible? 这可能吗? Currently compiler prints an "error: conversion to non-scalar type requested" message. 目前,编译器打印“错误:转换为请求的非标量类型”消息。

Probably the best solution would be to combine your two structs into a union. 可能最好的解决方案是将两个结构组合成一个联合体。 If you want to interpret the same data in two different ways then it's the obvious choice. 如果您想以两种不同的方式解释相同的数据,那么这是显而易见的选择。 The alternative is to use pointer casts, but that's ugly, breaks aliasing rules, and can hide errors that might otherwise be reported by the compiler. 另一种方法是使用指针强制转换,但这很难看,破坏了别名规则,并且可以隐藏编译器可能报告的错误。

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...
//

Well, you could just declare CATransform3DMakeScale like this: 好吧,您可以像这样声明CATransform3DMakeScale:

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

C doesn't type-check to make sure your deceleration matches the original library. C不进行类型检查以确保减速度与原始库匹配。 If the memory layout is the same, it will work. 如果内存布局相同,它将起作用。 However, it's bad coding practice and you should include a lengthy comment justifying your actions. 然而,这是糟糕的编码实践,你应该包括一个冗长的评论来证明你的行为。 ;-) ;-)

Otherwise, there's no way around it: you have to use pointers or copy the data. 否则,没有办法解决它:你必须使用指针或复制数据。 This would work: 这可行:

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

As you've discovered, you can't cast the structure directly. 正如您所发现的,您无法直接转换结构。 You also can't do this: 你也不能这样做:

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

because C only allows you to use the & operator on an l-value. 因为C只允许你在l值上使用&运算符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM