如何知道Union使用哪个变量?

Swa*_*and 15 c unions

如果我宣布一个联盟:

union TestUnion
{
    struct 
    {
      unsigned int Num;
      unsigned char Name[5];
    }TestStruct;
    unsigned char Total[7];
};
Run Code Online (Sandbox Code Playgroud)

现在,我怎么知道是使用了Total [7]还是使用了TestStruct?

我在用C!我正在重新审视工会和结构,我想到了这个问题." sizeof"不能用,因为它们都是相同的大小,即7个字节.(还有另一个问题)

当我只用字符'a'和Tried填充"Total"时sizeof(TestUnionInstance),它返回12(Char的大小是1字节,对吗?).所以我从中分离出结构,发现结构的大小是12个字节而不是5 + 2 = 7个字节....奇怪!! 谁能解释一下?

PS我正在使用Visual Studio 2008.

Tom*_*son 21

你不能.这是工会的一部分.

如果您需要能够分辨,您可以使用称为标记联合的东西.有些语言对这些语言有内置支持,但在C语言中,你必须自己做.我们的想法是包含一个标记以及union,您可以使用它来分辨它是哪个版本.喜欢:

enum TestUnionTag {NUM_NAME, TOTAL};

struct {
    enum TestUnionTag tag;
    union {
        struct {
            unsigned int Num;
            unsigned char Name[5];
        } TestStruct;
        unsigned char Total[7];
    } value;
} TestUnion;
Run Code Online (Sandbox Code Playgroud)

然后在您的代码中,确保始终设置标记以说明如何使用联合.

关于sizeof:struct是12个字节,因为int有4个字节(大多数现代编译器都有4个字节的int,与long int相同),然后是3个字节的填充和5个字节的字符(我不要不知道填充是在字符之前还是之后.填充是存在的,因此结构是长整数个字,因此内存中的所有内容在字边界上保持对齐.因为结构长度为12个字节,所以联合必须长12个字节来保存它; 工会不会根据其中的内容改变大小.

  • 填充在"char"之后,而不是之前.严格来说,一个实现*可以*在它之前添加填充,但是如果你从`char [5]`改为`char [6]`那么它也必须在它之前放入相同数量的填充,这将是非常荒谬的.C要求具有共同初始元素序列的结构是兼容的. (2认同)

pmg*_*pmg 6

要使用的成员是您上次写入的成员; 其他人是禁区.你知道你上次写信的成员,不是吗?毕竟,是你编写程序的人:-)


至于你的第二个问题:允许编译器在结构中插入"填充字节" 以避免未对齐的访问并使其更高性能.

example of a possible distribution of bytes inside your structure

Num    |Name     |pad
- - - -|- - - - -|x x x
0 1 2 3|4 5 6 7 8|9 a b

  • @thkala - 标准将此行为定义为未定义,因此它是禁止的,除非您明确依赖于依赖于平台的行为.在实践中,我知道`int is_little_endian(void){union {int i; char c [sizeof(int)]; 你 ui = 1; return uc [0] == 1; }`会这样做,但按照标准,代码是UB并且是邪恶的. (2认同)