关于联合和多个整数值
Regarding union and multiple integer values
我正在学习 C 并尝试使用 union。我的代码如下:
#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
return 的值为 28。
我认为您误解了工会的目的。如果你想要一个存储一组属性的对象(例如 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
视为超级块,例如,为了访问文件系统的索引节点数,您可以执行 current_block.super_block.n_inodes
(我想指出的是您不需要直接处理联合变量,你指定哪个 "type hat," 可以这么说,它应该穿。
联合是 C 中可用的一种特殊数据类型,它允许将不同的数据类型存储在同一内存位置。
也就是说,您必须一次使用一个变量。
引用 C11
,章节 §6.7.2.1,(强调我的)
The size of a union is sufficient to contain the largest of its members. The value of at
most one of the members can be stored in a union object at any time. A pointer to a
union object, suitably converted, points to each of its members (or if a member is a bitfield,
then to the unit in which it resides), and vice versa.
所以,你的预期基础是错误的。您不能同时拥有所有个工会成员的值,您只能拥有一个。
另外,从第 6.5.2.3 章,脚注 95,
If the member used to read the contents of a union object is not the same as the member last used to
store a value in the object, the appropriate part of the object representation of the value is re-interpreted
as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type
punning’’). This might be a trap representation.
这里,最后赋值day
恰好和month
的大小相同,所以当你尝试读取day
时,它returns month
.
的值
这完全误解了工会是什么。联合是一组值,它们都从相同的内存位置开始;如果你想在一种数据类型中存储多个单独的值,你需要使用的是结构。
例如,对于工会,您可以这样做:
#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
基本上,您分配一个值,所有联合成员都获得该值;如果它在不同类型中有不同的表示,那就这样吧。
在一个结构中,每个变量都占据自己的内存位置,因此如果您想将包括年、月和日的完整日期作为单独的变量存储在结构中,您可以毫无问题地这样做。
联合将其所有成员存储在同一个 space 中,并且 space 中存在的数据对应于最后写入的任何一个成员。工会与其最大的成员一样大。您没有提及您的特定平台,但假设现代 x86 Windows、MacOS 或桌面 Linux、char
可能是 8 位和 int
上的相当新的 GCC可能是 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 _/
应该清楚的是,写入联合的任何成员将至少覆盖所有其他成员的一部分。
将其与结构进行对比,结构对其所有成员具有独特的存储 space,使其至少与其所有成员加在一起一样大(填充可能更大)。如果您将示例代码中所有 union
的实例替换为 struct
,最后您会在内存中得到如下所示的内容:
1100 0000 0000 0111 0000 0000 0000 0000 0000 0111 0001 1100
\_______________ year ________________/ \ month / \_ day _/
每个成员的数据都完好无损,可以使用birth.year
、birth.month
或birth.day
正确检索。
我正在学习 C 并尝试使用 union。我的代码如下:
#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
return 的值为 28。
我认为您误解了工会的目的。如果你想要一个存储一组属性的对象(例如 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
视为超级块,例如,为了访问文件系统的索引节点数,您可以执行 current_block.super_block.n_inodes
(我想指出的是您不需要直接处理联合变量,你指定哪个 "type hat," 可以这么说,它应该穿。
联合是 C 中可用的一种特殊数据类型,它允许将不同的数据类型存储在同一内存位置。
也就是说,您必须一次使用一个变量。
引用 C11
,章节 §6.7.2.1,(强调我的)
The size of a union is sufficient to contain the largest of its members. The value of at most one of the members can be stored in a union object at any time. A pointer to a union object, suitably converted, points to each of its members (or if a member is a bitfield, then to the unit in which it resides), and vice versa.
所以,你的预期基础是错误的。您不能同时拥有所有个工会成员的值,您只能拥有一个。
另外,从第 6.5.2.3 章,脚注 95,
If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is re-interpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type punning’’). This might be a trap representation.
这里,最后赋值day
恰好和month
的大小相同,所以当你尝试读取day
时,它returns month
.
这完全误解了工会是什么。联合是一组值,它们都从相同的内存位置开始;如果你想在一种数据类型中存储多个单独的值,你需要使用的是结构。
例如,对于工会,您可以这样做:
#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
基本上,您分配一个值,所有联合成员都获得该值;如果它在不同类型中有不同的表示,那就这样吧。
在一个结构中,每个变量都占据自己的内存位置,因此如果您想将包括年、月和日的完整日期作为单独的变量存储在结构中,您可以毫无问题地这样做。
联合将其所有成员存储在同一个 space 中,并且 space 中存在的数据对应于最后写入的任何一个成员。工会与其最大的成员一样大。您没有提及您的特定平台,但假设现代 x86 Windows、MacOS 或桌面 Linux、char
可能是 8 位和 int
上的相当新的 GCC可能是 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 _/
应该清楚的是,写入联合的任何成员将至少覆盖所有其他成员的一部分。
将其与结构进行对比,结构对其所有成员具有独特的存储 space,使其至少与其所有成员加在一起一样大(填充可能更大)。如果您将示例代码中所有 union
的实例替换为 struct
,最后您会在内存中得到如下所示的内容:
1100 0000 0000 0111 0000 0000 0000 0000 0000 0111 0001 1100
\_______________ year ________________/ \ month / \_ day _/
每个成员的数据都完好无损,可以使用birth.year
、birth.month
或birth.day
正确检索。