将一个C结构铸造成另一个
我有两个相同的(但不同的名字)C结构:
typedef struct { double x; double y; double z; } CMAcceleration; typedef struct { double x; double y; double z; } Vector3d;
现在我想分配一个CMAccelerationvariables给Vector3dvariables(复制整个结构体)。 我该怎么做?
我尝试了以下,但得到这些编译器错误:
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;
但这似乎相当不方便。
什么是最好的解决scheme?
这是你唯一的解决scheme(除了包装成一个函数):
vector.x = acceleration.x; vector.y = acceleration.y; vector.z = acceleration.z;
你实际上可以投它,像这样(使用指针)
Vector3d *vector = (Vector3d*) &acceleration;
但是这并不在规范中,因此行为取决于编译器,运行时和大绿地怪物。
你可以使用指针来进行types转换;
vector = *((Vector3d *) &acceleration);
你为什么不使用。
typedef CMAcceleration Vector3d;
(而不是创build一个全新的结构)
在这种情况下vector = acceleration;
编译就好了。
你使用了一个实用的function:
void AccelerationToVector( struct CMAcceleration* from, struct Vector3d* to ) { to->x = from->x; to->y = from ->y; to->z = from->z; }
memcpy(&vector, &acceleration, sizeof(Vector3d));
请注意,如果内存中结构的物理布局是相同的,那么这只能起作用。 不过,@Oli指出,编译器没有义务确保这一点!
一个安全的(尽pipe有点复杂)的方法是使用一个联合:
union { CMAcceleration a, Vector3d v } tmp = { .a = acceleration }; vector = tmp.v;
当被访问的成员不是最后一个成员时,值被重新解释(从C99开始)。 在这种情况下,我们设置加速度,然后访问vector,所以加速度被重新解释。
例如,这是NSRectToCGRect函数的实现方式。
这通过一个联盟很容易实现:
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); }