2011-01-20 154 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 - 这是一个人为的例子,我敢肯定将打破。

相关问题