2010-05-20 99 views
5
typedef union { 
    float flts[4]; 
    struct { 
     GLfloat r; 
     GLfloat theta; 
     GLfloat phi; 
     GLfloat w; 
    }; 
    struct { 
     GLfloat x; 
     GLfloat y; 
     GLfloat z; 
     GLfloat w; 
    }; 
} FltVector; 

好的,所以我想我得到如何使用這個,(或者,這是我如何看到它使用)ie。尋求C Union清晰度

FltVector fltVec1 = {{1.0f, 1.0f, 1.0f, 1.0f}}; 
float aaa = fltVec1.x; 
etc. 

但我真的不groking多少存儲已經由工會宣佈(4輛花車?8輛花車?12個浮點?),怎麼樣?爲什麼?另外爲什麼兩套花括號使用FltVector {{}}?

爲什麼要使用聯合?爲什麼不這樣做..

struct FltVector { 
     GLfloat x; 
     GLfloat y; 
     GLfloat z; 
     GLfloat w; 
    } 

任何指針讚賞(抱歉的雙關語)

回答

5

if if sizeof(GLfloat) == sizeof(float) then,4 floats has been allocated。

flts[0]rx這裏都是指同一塊內存。

在一個聯合中,在聯合中聲明的每個不同的變量都指向同一塊內存。

這裏我們有3個變量,2個結構體和一個數組,每個都在內存中的相同位置開始。

5

一個工會,您可以「回收」同樣的內存用於不同類型的變量區域。通常情況下,工會需要儘可能多的存儲,因爲它可能只有4個浮動。你可以用sizeof查詢。

在這種情況下的聯合可能是用於提供1)相同的浮替代名稱在struct(例如xr共享相同的存儲器),和2)訪問相同四個浮點作爲陣列(例如,xflts[0]共享相同的內存)。有時工會被用於各種「黑客」,通常是非便攜式的,以訪問某些數據類型的內部,例如機器順序中的整數中的單個字節。

+0

這就是在這種情況下:4浮點數(如果GLfloat等於浮點數) – tur1ng 2010-05-20 11:42:21

2

有幾個問題:)

@Arkku是正確的大小。對齊也可以起作用,但可能不在這裏。

爲什麼這是真的,在任何給定的時間,聯盟只有一個可能的值。由於這個原因,通常在一個結構中存在一個標識哪個值有效的聯合(有時稱爲歧視聯盟scrim)。

一對大括號用於聯合,另一個用於數組initalizer。

1

爲什麼兩套大括號的使用FltVector時,{{}}

看整條生產線,FltVector fltVec1 = {{1.0f, 1.0f, 1.0f, 1.0f}}; 你初始化四個浮點第一結構的聯盟。正如你從粗體的「in」中看到的那樣,有兩層嵌套。如果嵌套層次更深,你甚至可以擁有更多的花括號。

+0

是的,但是這裏我們可以不加刪除一組大括號,因爲它會初始化第一個內部結構。 – kriss 2010-05-20 12:22:02

1

在你的例子中,如果我們考慮變量的名字,union肯定不是用來通過x和r來訪問同一個存儲單元(因爲半徑和x座標不太合適),但讓用戶爲兩者提供相同的參數。當使用笛卡爾座標時,設置x,y,z,w會簡單得多,並且在徑向座標中使用相同的名稱會很困難。兩者都比數組索引更簡單。您可能還有另外一個參數,它提供所提供的座標的類型(笛卡爾或徑向)。因此,當pdbartlett調用它們時,你將會有一個歧視的工會。

在這種情況下,雙層花括號是無用的,因爲數組可以通過數組(雙層括號)或通過內部結構之一進行初始化。

更正:大括號的雙級別避免將輸入輸入到GLFloats。

最後的細節:無名內部結構不標準C,做事的標準方法是給名內部結構就像

typedef union { 
    float flts[4]; 
    struct { 
     float r; 
     float theta; 
     float phi; 
     float w; 
    } cartesian; 
    struct { 
     float x; 
     float y; 
     float z; 
     float w; 
    } radial; 
} FltVector; 

FltVector f = {1.0, 2.0, 3.0, 4.0 }; 

int main(int argc, char * argv[]){ 
    printf("flts[0]=%f f.radial.r=%f f.cartesian.x=%f\n", 
     f.flts[0], f.radial.r, f.cartesian.x); 
} 
+0

感謝大家的幫助,現在真的很清楚了。 – hooleyhoop 2010-05-20 14:27:27

+0

這不是「更平常」,它實際上是語言所必需的。它由於非標準的編譯器擴展而編譯時沒有這些名稱。 – AnT 2010-05-22 01:15:01

+0

@AndreyT:我會編輯答案,我沒有檢查標準(無論如何,我不是一個真正的標準信徒,並且把編譯器當成真正的東西。在我眼中,stndard只是避免太多熵的工具,引導語言進化)。 – kriss 2010-05-22 08:36:58

0

正如人們已經注意到,在代碼中使用不同的分配相同的內存名稱和數據類型。它有時可以被允許處理命名向量組件(xyzw),同時仍然可以將向量作爲一個數組在其他時間處理。

雖然它看起來像笛卡爾和徑向結構的名稱交換。 「r」,「theta」和「phi」是徑向座標的通用名稱,而不是通常表示爲「x」,「y」和「z」的笛卡爾座標。

我認爲這是值得注意的是,使用不同的表示方法不嚴格符合標準的(但可能工作正常,所有現有的C-實現),有兩個原因:

  1. 閱讀工會成員不是最近寫入的結果爲未定義結果。不過,任何理智的實現都會返回存儲在內存中的值。
  2. 編譯器可能會在結構成員之間添加填充(出於性能原因),而數組從不填充。不過,這種情況在任何現代CPU上都不太可能發生。