2011-01-20 75 views

回答

11

您可以在聯合中使用任何數據類型,沒有限制。關於聯合在結構上的使用,結構在存儲器中順序地佈置它們的數據。這意味着所有的子組件都是分開的。

另一方面,工會對其所有子部件使用相同的內存,因此一次只能存在一個。

例如:

        +-----+-----+ 
struct { int a; float b } gives | a | b | 
           +-----+-----+ 
            ^ ^
            |  | 
       memory location: 150 154 
            | 
            V 
           +-----+ 
union { int a; float b } gives | a | 
           | b | 
           +-----+ 

結構所使用的地方的「對象」是由其它的目的,如由兩個整數,它們是x和y的點對象的座標:

typedef struct { 
    int x;   // x and y are separate 
    int y; 
} tPoint; 

工會通常用於以下情況:對象可以是許多事物中的一種,但一次只能有一種,例如無類型存儲系統:

typedef enum { STR, INT } tType; 
typedef struct { 
    tType typ;   // typ is separate. 
    union { 
     int ival;  // ival and sval occupy same memory. 
     char *sval; 
    } 
} tVal; 

它們對於節約內存非常有用,儘管現在這種情況往往越來越少(除了像嵌入式系統這樣的低級工作以外),所以你沒有看到太多內容。

+0

工會不是爲了節省內存:它們表達* sum類型*,即。一種持有例如。 * * float *或* int。工會很難使用,而且相當有限。請考慮使用`boost :: variant`來代替。 – 2011-01-20 15:09:08

4

那麼,根據ISO/IEC 9899:TC3(C99標準):

甲聯合類型描述了一種重疊的非空集成員的對象,每個 ,其具有任選的指定名稱和可能不同的類型。

簡而言之,聯合成員的內存空間重疊,並且您給聯合成員的名稱允許您在該位置讀取內存大小。考慮:

#include <stdio.h> 
#include <stdint.h> 

typedef union 
{ 
    struct 
    { 
     uint8_t a; 
     uint8_t b; 
     uint8_t c; 
     uint8_t d; 
    }; 
    uint32_t x; 
} somenewtype; 

typedef union 
{ 
    uint32_t* p; 
    uint8_t* q; 
} somepointer; 

int main(int argc, char** argv) 
{ 
    uint32_t r; 
    uint8_t s; 
    somenewtype z; 
    somepointer p; 
    r = 0x11223344; s = 0x11; 
    z.x = 0x11223344; 
    p.p = &r; 
    p.q = &s; 
    printf("%x%x%x%x\n", z.d, z.c, z.b, z.a); 
    printf("%x %x\n", *(p.p), *(p.q)); 
} 

在第一個printf中,我們正在做的是打印32位整數的8位部分。當然希望在那個匿名結構中沒有填充。

在第二個printf?我不得不介入,通過使用gdb的理解,但我所做的:

p.p = (uint32_t *) 0x7fffffffde5c; 
p.q = (uint8_t *) 0x7fffffffde5b "\021D3\"\021P\337\377\377\377\177"; 
p.p = (uint32_t *) 0x7fffffffde5b; 

當然好了,指針都一樣大小,因此分配p.q覆蓋的p.p地址。我強烈地懷疑,將32位整數的地址解除引用到8位指針時,會打印出「該位置處的任何內容+ 32位大小」,這對我來說恰好是22334411。但我懷疑,在那個時候,行爲是不確定的。

無論如何,這一點練習的要點是你表明:

  • 工會可以通過使用不同的「類型」修改器來訪問相同的存儲位置。
  • 你必須小心你所做的事,並理解你所使用的基礎類型。如果您要使用指針,請注意他們的修改,因爲您可能會開始指向誰知道什麼。

我要指出,我可以看到實際使用的somenewtype而不是somepointer - 這是一個人爲的例子,我敢肯定將打破。

相關問題