【问题标题】:How does C interpret data from a union if it's formatted differently?如果格式不同,C 如何解释来自联合的数据?
【发布时间】:2015-06-08 00:42:41
【问题描述】:
main()
{
union{
    char i[2];
    struct{
        short age;
    } myStruct;
} myUnion;
myUnion.i[0] = 'A';
myUnion.i[1] = 'B';
printf("%x ", myUnion.myStruct.age);

} 

所以我知道联合只包含其中最大成员的空间 - 在这种情况下,字符数组“i”和结构“myStruct”似乎是相同的,所以联合只有两个字节包含字符“A”和“B”。但是,如果此时您尝试读取结构成员“age”会发生什么?

【问题讨论】:

  • 你为什么不试试呢?您会看到一个基于 'A' (0x61) 和 'B' (0x62) 的值,0x6162 或 0x6261,具体取决于它是大端还是小端机器。当心,名义上你正在陷入未定义的行为。在实践中,还没有编译器编写者疯狂到破坏这样的代码。
  • @JonathanLeffler:从 C99 开始,它不再是 UB。
  • @DietrichEpp:你能指定章节吗?第 6.7.2.1/16 节说 联合的大小足以容纳其最大的成员。任何时候最多可以将其中一个成员的值存储在联合对象中。一个指向联合对象的指针,经过适当的转换,指向它的每个成员(或者如果一个成员是位域,则指向它所在的单元),反之亦然。 at大多数成员的部分意味着仍然存在一些限制。什么可以让您访问上次未存储的值?
  • 哦翻转;我的第一条评论使用了'a''b' 的十六进制代码,而不是'A''B',它们应该是0x41 和0x42。相应地调整其余部分。
  • @JonathanLeffler: n1570 §6.2.6.1 第 7 段。

标签: c memory struct unions


【解决方案1】:

在过去的几天里,这是“未定义的行为”,理论上可能会使您的系统崩溃或更糟。然而,程序员还是这样做了,它被编入 C99(参见Is type-punning through a union unspecified in C99, and has it become specified in C11?),允许你这样做,但没有说明结果会是什么,或者它们是否有意义。

所以,

  • 在现代 8 位字节 16 位短 little-endian 系统上,它将打印 4241

  • 在现代 8 位字节 16 位短大端系统上,它将打印 4142

  • 如果sizeof(short) > 2那么你就有问题了,因为age是未初始化的(但是这些系统非常少见),

  • 您将在 EBCDIC 上得到不同的结果(您不使用或不关心),

  • 您将在非 8 位字节系统(您不使用或不关心)上得到不同的结果,

  • 如果您的程序为 short... 创建陷阱表示,您可以调用未定义的行为...但是,现代系统没有整数的陷阱表示。

【讨论】:

    猜你喜欢
    • 2021-11-01
    • 1970-01-01
    • 2018-07-25
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多