定义和访问联合体和结构体的成员

问题描述 投票:0回答:2

我有三个可能的定义,但我很困惑为什么有这么多。 访问成员的行为与其他成员的行为有什么不同吗? 优缺点都有什么?只是想知道在使用这些之前是否需要考虑一些规则。

对于

a
r
g
b
color
,我想根据数据类型访问内存中的组件,或者在同一内存中检索
unsigned int
color
位置。

struct RGBColor
{
    union
    {
        BYTE a, r, g, b;
        UINT color;
    };
};
struct RGBColor2
{
    union { BYTE a, r, g, b; };
    union { UINT color; };
};
union RGBColor3
{
    struct { BYTE a, r, g, b; };
    struct { UINT color; };
};

我试图寻找一个简单的答案,但找不到任何答案。

c++ struct union
2个回答
4
投票

您误解了工会的运作方式。第一个结构体包含一个具有五个替代项的联合:名为 a 的字节、名为 r 的字节,依此类推。

第二个结构体包含两个联合。第一个包含四个字节中的一个,但一次只能一个,第二个始终包含一个 uint。

第三是正当的联合。它包含四个字节的结构或包含颜色的结构。现在我不知道你的计划是什么,但是将四个字节存储到第一个替代方案中并将它们作为颜色读取是未定义的行为。更糟糕的是,这种未定义的行为在某些编译器上“有效”,但在其他编译器上却无效。或者更糟糕的是,在开发版本中而不是发布版本中。

(未定义的行为怎么会不“工作”?假设你在 Color 中写入了一个零。然后你写入了 a、r、g 和 b 并读取了 Color。编译器说“你在 Color 中写入了 0,你没有写入任何内容”否则为 Color,因此 Color 必须为 0”。或者编译器说“你写 a、r、g 和 b,然后读取 Color。这是未定义的行为,所以我删除了四个字节存储”。)


0
投票

正如评论所建议的(我无法评论,我没有代表),struct RGBColor 和 struct RGBColor2 的“缺点”是它们可能不是您想要的。考虑它们可以写成

struct RGBColor
{
    union
    {
        BYTE a;
        BYTE r;
        BYTE g;
        BYTE b;
        UINT color;
    };
};

struct RGBColor2
{
    union {
        BYTE a;
        BYTE r;
        BYTE g;
        BYTE b;
    };
    union { UINT color; };
};

因此 RGBColor 将允许您访问 a 或 r 或 g 或 b 或颜色,而 RGBColor2 将允许您访问 a 或 r 或 g 或 b 和颜色。具有一个成员的联合(作为 RGBColor2 的第二个字段,UINT color)本质上是多余的,因为它仅意味着该字段。

第三个版本 RGBColor3 可以满足您的要求,不过,正如还指出的那样,UINT 可以是任何大小,具体取决于目标架构,因此来自 stdint.h 的 uint32_t 会更好,因为它保证为 4字节,。如果我们要使用 stdint.h,我还会使用 uint8_t 以使字节保持一致。此外,具有一个字段的结构,就像具有一个字段的联合一样,是多余的,因此可能可以更好地表示为

union RGBColor3 {
    struct {
        uint8_t a;
        uint8_t r;
        uint8_t g;
        uint8_t b;
    };
    uint32_t color;
};

这将允许您单独访问四个字节的颜色,或作为 32 位值访问。

© www.soinside.com 2019 - 2024. All rights reserved.