关于并集和多个整数值

时间:2017-06-06 19:55:23

标签: c unions

我进入C并试验了工会。我的代码如下:

#include <stdio.h>

union date {
 int year  ;
 char month;
 char day  ;
 };

int main() {
 union date birth;
 birth.year = 1984;
 birth.month = 7;
 birth.day = 28;
 printf("%d, %d, %d\n",birth.year, birth.month, birth.day);
 // return 1820,28,28
 return 0;
}
  • 1984以二进制形式写成0111 1100 0000

  • 7以二进制形式写成0110

  • 28以二进制形式写为0001 1100

我理解由于联合,birth.year的值为0111 0001 1100,即1820.但我不明白为什么birth.month返回值为28.

5 个答案:

答案 0 :(得分:4)

我认为你误解了工会的目的。如果您想要一个存储一组属性的对象(例如d.yeard.monthd.day),则需要一个结构。

简而言之,工会允许您将多种不同类型中的一种放在一个变量中。比如说你正在实现一个文件系统。假设您想要一个变量current_block,它可以分别引用由struct super_blockstruct data_block定义的超级块或数据块。然后你可以这样做:

union block_generic{
    struct super_block;
    struct data_block;
}

union block_generic current_block;

现在current_block可以是super_block或data_block。

编辑:只想添加关于工会实际使用情况的快速补遗。继续上面的例子,将current_block视为超级块,例如,为了访问文件系统的inode数量,你会做current_block.super_block.n_inodes(我的意思是指出你不是直接处理union变量,你指定哪个“类型帽子”,可以这么说,它应该穿。

答案 1 :(得分:2)

引用C11,章节§6.7.2.1,(强调我的

  

联合的大小足以包含其最大的成员。 at的值   大多数成员可以随时存储在union对象中。指向a的指针   联合对象,适当转换,指向其每个成员(或如果成员是位域,   然后到它所在的单位),反之亦然。

所以,你期望的基础是错误的。您不能同时拥有所有联盟成员的值,您只能拥有一个。

另外,从章节§6.5.2.3,脚注95,

  

如果用于读取union对象内容的成员与上次使用的成员不同   在对象中存储值,重新解释值的对象表示的适当部分   作为6.2.6中描述的新类型中的对象表示(有时称为''类型的过程)   双关语””)。这可能是陷阱表示。

此处,最后指定的值day恰好与month的大小相同,因此当您尝试阅读day时,它会返回该值的值month {{1}}。

答案 2 :(得分:1)

union将其所有成员存储在同一空间中,该空间中存在的数据对应于最后写入的成员。联盟与其最大的成员一样大。你没有提到你的特定平台,但假设在现代x86 Windows,MacOS或桌面Linux上有一个相当新的GCC,char可能是8位,int可能是32位,使你的约会工会看起来像这样:

0000 0000 0000 0000 0000 0000 0000 0000
\_______________ year ________________/
\ month /
\_ day _/

让我们一起讨论union date birth的用法,好吗?从birth.year = 1984;开始,我们(请记住x86是little endian

1100 0000 0000 0111 0000 0000 0000 0000
\_______________ year ________________/
\ month /
\_ day _/

然后birth.month = 7;

0000 0111 0000 0111 0000 0000 0000 0000
\_______________ year ________________/
\ month /
\_ day _/

最后,birth.day = 28;

0001 1100 0000 0111 0000 0000 0000 0000
\_______________ year ________________/
\ month /
\_ day _/

应该很清楚,写入工会的任何成员都会覆盖至少部分其他成员。

将结构与其所有成员具有唯一存储空间的结构进行对比,使其至少与其所有成员一起添加(与填充相比可能更大)。如果您使用union替换示例代码中的struct的所有实例,那么最终会在内存中看到这样的内容:

1100 0000 0000 0111 0000 0000 0000 0000 0000 0111 0001 1100
\_______________ year ________________/ \ month / \_ day _/

每个成员的数据完整无缺,可以使用birth.yearbirth.monthbirth.day正确检索。

答案 3 :(得分:0)

union是C中可用的特殊数据类型,允许在同一内存位置存储不同的数据类型。

那就是说,你必须一次使用一个变量。

http://www.tutorialspoint.com/cprogramming/c_unions.htm

答案 4 :(得分:0)

这完全误解了工会是什么。 union是一组值,它们都从相同的内存位置开始;如果要在一个数据类型中存储多个单独的值,则需要使用的是结构。

例如,使用联合可以执行此操作:

#include <stdio.h>
#include <stdint.h>

typedef union _myunion
{
    int32_t s;
    uint32_t u;
} myunion;

int main()
{
    myunion u;
    u.s = -1;
    printf("%d %u\n", u.s, u.u);
    return 0;
}   

输出:

-1 4294967295

基本上,您指定一个值,所有工会成员都获得该值;如果它以不同的类型表示不同,那就这样吧。

在结构中,每个变量占用自己的内存位置,因此如果您想将包含年,月和日的完整日期作为结构中的单独变量存储,则可以毫无问题地这样做。