c - union 成员如何存储?

标签 c endianness unions

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

假设sizeof(int)==2,设分配给t的内存地址为2000、2001。
那么 20 即 t.ch 存储在哪里 - 在 2000 或 2001 或取决于机器的字节顺序?

最佳答案

C99 标准 (§6.7.2.1.14) 说:

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 bit- field, then to the unit in which it resides), and vice versa.

(强调)

大胆的说法实际上是说联盟的每个成员都有相同的地址,所以他们都“开始”在同一个地址。 t,作为t.ch作为t.i,应该在地址2000,因此t.cht.i 的第一个字节(按地址顺序)。

在现实世界中,“如果我在设置 t.c 后尝试读取 t.i 会得到什么”,这意味着什么取决于平台字节序,事实上根据 C 标准(§6.2.6.1.6/7,在 §J.1.1 重述),当您在另一个 union 体中写入时尝试读取一个 union 体的成员是未指定的行为。


更有助于理解机器的字节顺序(至少,我认为它更容易理解)的是有一个像这样的 union :

union
{
    int i;
    unsigned char ch[sizeof(i)];
} t;

t.i=20;

然后在 t.ch 中查看两个字符中的内容。如果你在小端机器上,你会得到 t.ch[0]==20t.ch[1]==0,反之如果您使用的是大端计算机(如果 sizeof(int)==2)。请注意,如前所述,这是一个特定于实现的细节,该标准甚至没有提及字节顺序。

为了让它更清楚:如果你有一个 2 字节的 int var 设置为 20,在小端机器上,以地址顺序转储与其关联的内存,你会get(十六进制表示,字节按空格分割):

14 00

在大端机器上你会得到

00 14

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


Moreover I am saying that if I do this:

int a=20;
printf("%d",* (char*)&a);

Then doesn't the output depend on endian-ness i.e. whether 20 is stored at 2000 or 2001 ?

是的,确实如此,但在您的问题中您是在问另一件事;这看起来更像是的例子。

关于c - union 成员如何存储?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4540638/

相关文章:

c# - 如何模拟 BitConverter.IsLittleEndian 与我的单元测试相反的环境?

c++ - C++中文件的Big Endian和Little Endian

C++ union 数据结构,轻松访问 DWORD 中的位

c - 在C中读取和写入unicode字符到文件

c - 段错误 : concatenating string

python - 使用 struct.pack 的字节顺序 struct.unpack

c++ - 使用 Flatbuffer Union 通过 ZeroMQ 发送不同的事件

c - 为什么 X 在此代码中未定义?

c - 硬件处理器计数器重置不正确

c - 对 union 中的字符进行 strcpy 时程序中止