我进入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.
答案 0 :(得分:4)
我认为你误解了工会的目的。如果您想要一个存储一组属性的对象(例如d.year
,d.month
,d.day
),则需要一个结构。
current_block
,它可以分别引用由struct super_block
和struct 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.year
,birth.month
或birth.day
正确检索。
答案 3 :(得分:0)
union是C中可用的特殊数据类型,允许在同一内存位置存储不同的数据类型。
那就是说,你必须一次使用一个变量。
答案 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
基本上,您指定一个值,所有工会成员都获得该值;如果它以不同的类型表示不同,那就这样吧。
在结构中,每个变量占用自己的内存位置,因此如果您想将包含年,月和日的完整日期作为结构中的单独变量存储,则可以毫无问题地这样做。