联合结构有什么作用?

时间:2013-06-17 06:56:54

标签: c++ c struct unions

我不知道如何破译这个男人有人需要告诉我发生了什么事请帮助

typedef struct _ARGBCOLOR {
    union {
        struct {
            BYTE B;
            BYTE G;
            BYTE R;
            BYTE A;
        };
        DWORD ARGB;
    };
} ARGBCOLOR, *PARGBCOLOR;

5 个答案:

答案 0 :(得分:7)

如果您有ARGBCOLOR x;您可以访问4个单独的字节x.Bx.Gx.Rx.A,或32位字为x.ARGB

C标准保证这些将适当地覆盖(假设尺寸适合和填充要求不会拧紧狗(这里不是这种情况))。但是这个结构显然假设了一个小端系统。

一个额外的复杂因素是联盟是匿名的。命名一个像u这样的联合是很常见的,但是有些编译器允许内部联合和结构是匿名的,因此它们的成员被访问就像它们在一个级别上一样(与联合本身处于同一级别)。 / p>

我最喜欢这种叠加类型的方法是将联合放在最外层。您可以复制kindtype成员,以便随处访问。但这种方式消除了使用匿名联合(在Ansi-C或C99中不可用)的诱惑,因为你不需要在中间伪造u成员。

typedef union _ARGBCOLOR {
    //BYTE type;
    struct {
        //BYTE type;
        BYTE B;
        BYTE G;
        BYTE R;
        BYTE A;
    } bytes;
    struct {
        //BYTE type;
        DWORD ARGB;
    } word;
} ARGBCOLOR, *PARGBCOLOR;

由于公共初始前缀属性,所有三个BYTE type;成员都会覆盖相同的内存。

另一种变化是为各个字节创建一个数组。

typedef union _ARGBCOLOR {
    DWORD dword;
    BYTE byte[ sizeof(DWORD)/sizeof(BYTE) ];
} ARGBCOLOR, *PARGBCOLOR;
enum { B,G,R,A };

现在我们不需要两个级别,并且类型惩罚更明显。

ARGBCOLOR x = { 0x10203040 };
x.byte[B] = 50;
x.byte[G] = 60;
printf("0x%8x\n", x.dword);  // prints: 0x10206050

答案 1 :(得分:2)

它声明了union之外的结构会做同样的事情,但允许你匿名地做,将struct的成员暴露为与其他union成员相同的作用域。您的构造特别允许您执行类似

的操作
ARGBCOLOR a;
printf("a = %u.%u.%u.%u or %lu\n", a.B, a.G, a.R, a.A, a.ARGB);

(联合本身允许您将其视为联合中的一种类型,在这种情况下,您可以将其视为四个BYTE值的序列或单个DWORD值)

如果您将结构定义从联合中提升出来:

struct ARGB_VALUES {
    BYTE B, G, R, A;
};
struct ARGBCOLOR {
    union {
        ARGB_VALUES VALUES; /* My god, how can you tell a type from a member? */
        DWORD ARGB;
    };
};

之前的printf必须是:

ARGBCOLOR a;
printf("a = %u.%u.%u.%u or %lu\n", a.VALUES.B, a.VALUES.G, a.VALUES.R, a.VALUES.A, a.ARGB);

注意:您正在使用的结构定义构造非常陈旧。您可以按如下方式减少它,并为每个结构/类保存第二个使您的符号表膨胀的别名:

typedef struct ARGBCOLOR {
    ...
} *PARGBCOLOR;

你这样做的方式与此相同:

struct _ARGBCOLOR {}; // First symbol.
typedef _ARGBCOLOR ARGBCOLOR;
typedef _ARGBCOLOR *PARGBCOLOR;

答案 2 :(得分:1)

typedef struct _ARGBCOLOR 
{
    union 
    {
        struct 
        {
            BYTE B;
            BYTE G;
            BYTE R;
            BYTE A;
        };

        DWORD ARGB;
    };
} ARGBCOLOR, *PARGBCOLOR;

如果您仔细观察,可以在union中看到structDWORD。您可以使用typedefed struct ARGBCOLOR中的任何一个,无论哪个可用

答案 3 :(得分:1)

最外层的结构在你的例子中并不是真的有用,但是它有一个名为kind的附加成员或者其他成员:

struct ARGBCOLOR {
    uint8_t kind;
    union {
        struct {
            BYTE B;
            BYTE G;
            BYTE R;
            BYTE A;
        };
        DWORD ARGB;
    };
} ARGBCOLOR;

然后,根据kind的值,您将联合解释为 包含成员BGR和{的结构{1}}, DWORD A

编辑:请记住,诸如union和内部结构之类的匿名成员只会成为C11中C标准的一部分。

答案 4 :(得分:1)

在联合中,每个数据成员都从内存中的相同位置开始。 DWORD ARGB以4个字节共享struct的内存位置。因此,union的大小将为4个字节,您可以使用ARGB或按字节顺序使用ARG作为整体访问它,或B(可以修改单个字节而不影响其他字节)。