C 工会成员是如何储存的?

C 工会成员是如何储存的?,c,endianness,unions,C,Endianness,Unions,假设sizeof(int)==2,并让分配给t的内存地址为20002001。 那么,20即t.ch存储在哪里?是在2000年还是2001年,还是取决于机器的端部?测试将占用两个字节,因此将分配在地址2000、2002等处。联合的每个实例的任何值都将从该基址开始存储 该联盟的每个成员将被存储在该联盟实例的同一地址。这就是为什么在同一时间只能在联合中存储一种类型的值。因此,联合占用最大成员所需的字节数。C99标准(§6.7.2.1.14)规定: 工会的规模足以容纳其最大的成员。at的价值 大多数成员

假设
sizeof(int)==2,并让分配给t的内存地址为20002001。

那么,20即
t.ch
存储在哪里?是在2000年还是2001年,还是取决于机器的端部?

测试将占用两个字节,因此将分配在地址2000、2002等处。联合的每个实例的任何值都将从该基址开始存储

该联盟的每个成员将被存储在该联盟实例的同一地址。这就是为什么在同一时间只能在联合中存储一种类型的值。因此,联合占用最大成员所需的字节数。

C99标准(§6.7.2.1.14)规定:

工会的规模足以容纳其最大的成员。at的价值 大多数成员可以随时存储在联合对象中指向 经过适当转换的union对象指向其每个成员(或者如果成员是位- 字段,然后发送到它所在的单元),反之亦然

(增加重点)

这句粗体的话实际上是说,工会的每个成员都有相同的地址,所以他们都“开始”在同一个地址
t
,如
t.ch
as
t.i
,应位于地址2000处,因此
t.ch
t.i
的第一个字节(按地址顺序)重叠

在现实世界中,“如果我在设置
t.c
后尝试阅读
t.I
”这意味着什么,取决于平台端性,而事实上,当你在另一个联盟中写作时尝试阅读联盟成员是根据c标准(第6.2.6.1.6/7节,在第J.1.1节中重申)的未指定行为


更能帮助理解机器的终结性(至少,我认为理解起来更简单)的是有这样一个联合体:

union test
{
 int i;
 char ch;
}t;
int main()
{
 t.ch=20;
}

然后在
t.ch
上查看两个字符内的内容。如果你在一台小端机上,你会得到
t.ch[0]==20
t.ch[1]==0
,如果你在一台大端机上,情况正好相反(如果
sizeof(int)==2
)。请注意,如前所述,这是一个特定于实现的细节,标准甚至没有提到endianness

更清楚地说:如果将2字节
int
var设置为20,则在一台小型endian机器上,按地址顺序转储与其关联的内存,您将得到(十六进制表示,字节按空格分割):

在big endian机器上你会

14 00
从我们的角度来看,大端表示法看起来“更正确”,因为在小端表示法中,构成整个
int
的字节以相反的顺序存储


此外,我要说的是,如果我这样做:

那么,输出是否取决于endian ness,即20是存储在2000年还是2001年


是的,这里有,但在你的问题中,你问的是另一件事;这更像是我的例子。

我不确定endian ness是否与union的存储位置有关。。。难道不是所有的联合类型都存储在同一位置(即零偏移处)?(尽管这是个好问题!)2001不太可能,因为未对齐的内存访问速度慢或被禁止取决于体系结构。@Platinum Azure:如果我们只定义int a=20;那么这不取决于存储20的字节数吗?@Happy Mittal:不,因为你刚才说它使用两个字节(在你的例子中是2000和2001)。现在,高位(代表16位和4位)是在2000年还是在2001年取决于endian的大小,但事实仍然是,无论哪个字节包含设置位,另一个字节仍然不可用,因为它是
int
类型存储空间的一部分。@platinum Azure:对不起,我不明白你说的是什么意思“16和4位”。此外,我是说如果我这样做:int a=20;printf(“%d”,*(char*)&a);那么,输出是否取决于endian ness,即20是存储在2000还是2001?谢谢Matteo。实际上你和Platinum Azure说的是相反的话,所以我很困惑。@Happy Mittal:正如我在最新评论中解释的,但这是我使用的旧评论,它具有int到char的转换。事实仍然是:一个16位的数字由文字表示的
20
仍然存储在两个字节中,无论您的体系结构使用的是什么endianness。只是一个字节或另一个字节将为零。如果要存储像
257
这样的数字,两个字节都将为非零。
t.i=20;
14 00
00 14
int a=20;
printf("%d",* (char*)&a);