2010-05-02 45 views
10

我有2層矩陣結構意味着等於數據但具有不同的形式這樣的:如果C結構只是另一個結構類型,如果他們的內存大小相等?

// 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); 

這可能嗎?目前編譯器打印出「錯誤:轉換爲非標量類型請求」消息。

回答

16

可能最好的解決方案是將你的兩個結構組合成一個聯合。如果你想用兩種不同的方式解釋相同的數據,那麼這是明顯的選擇。另一種方法是使用指針轉換,但這很醜,打破了別名規則,並且可以隱藏編譯器可能會報告的錯誤。

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

輝煌。但在我看來,它需要一種代理變量。它不會導致一些複製? – Eonil 2010-05-02 09:41:00

+0

否 - 僅將聯合定義爲typedef - 參見上面的示例。 – 2010-05-02 09:44:28

+1

工會是最好的主意。大多數類型安全,最簡單的轉換,沒有開銷。 – Puppy 2010-05-02 14:26:30

1

嗯,你可以只是聲明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只允許您使用&操作上的左值。

+1

這是通過指針轉換的「類型雙關」 - 它打破了別名規則,並且應該用任何體面的編譯器生成警告。請參閱:http://en.wikipedia.org/wiki/Type_punning。請注意,聯合技巧也嚴格意義上說是UB,但通常認爲它比指針轉換方法更安全。 – 2010-05-02 15:13:09

+1

@ Paul R:好點。我已經更新了我的答案。 – 2010-05-02 16:31:03