如何在C中访问联合

时间:2014-12-03 10:24:11

标签: c unions

我对使用union感到困惑,我尝试了不同的方法来访问它失败了。一个例子:

union 
{
    struct 
    {
        char cycle;
        char freq;
        char id;
    } Umember_a;

    char Umember_b[3];
} data_u;

char info[3];

我想复制" info"数组到联合" data_u",但是如果我使用以下任何一个,我发现有错误:

memcpy(data_u, info, sizeof(data_u));
memcpy(&data_u, info, sizeof(data_u));
memcpy(data_u.Umember_a, info, sizeof(data_u));
memcpy(data_u.Umember_a, info, sizeof(data_u.Umember_a));

但我可以使用:

memcpy(data_u.Umember_b, info, sizeof(data_u.Umember_b));
memcpy(&data_u.Umember_a, info, sizeof(data_u.Umember_a);

你能帮我解释一下吗?

2 个答案:

答案 0 :(得分:4)

不幸的是,这种方法注定要失败,因为您假设cyclefreqid紧密地包含在结构中。情况不一定如此:编译器可以自由选择任何方式对齐结构成员。

可以使用info Umember_b复制到memcpy。这将是安全的,因为(i)保证阵列是连续的,并且(ii)Umember_b[0]的地址将与data_u的地址相同。但是你不知道memcpy如何在Umember_a的元素中分配自己。

有些编译器允许您更改结构包装,但这根本不够便携,不可靠。

答案 1 :(得分:0)

显然你不能做memcpy(data_u, info, sizeof(data_u));之类的事情,因为memcpy需要一个指针,但你传递一个变量。这与工会无关。将指针传递给memcpy 的情况不应该给出错误。因为在C中,任何指针都可以隐式地转换为void* /从memcpy(&data_u, info, sizeof(data_u));转换。如果你在这里收到错误,那是因为你错误地将你的C代码编译为C ++,它有更严格的类型要求。

memcpy(data_u.Umember_b, info, 3);将起作用,但严格来说这会破坏C的别名规则。特别是因为C struct / union可能包含填充字节。无论你打算如何处理这个联盟,都需要考虑填充。

{{1}}是最安全,最正确的方法。它是否真的有效取决于是否有填充。