【问题标题】:Understanding the memory content of a union了解联合的内存内容
【发布时间】:2010-03-04 04:32:54
【问题描述】:

假设我这样定义一个联合:

#include <stdio.h>

int main() {
    union u {
        int i;
        float f;
    };
    union u tst;
    tst.f = 23.45;

    printf("%d\n", tst.i);

    return 0;
}

谁能告诉我tst 存储的内存是什么样的?

我试图了解该程序产生的输出1102813594

【问题讨论】:

    标签: c++ c memory memory-management unions


    【解决方案1】:

    这取决于实现(编译器、操作系统等),但如果需要,您可以使用调试器实际查看内存内容。

    例如,在我的 MSVC 2008 中:

    0x00415748  9a 99 bb 41
    

    是内存内容。从左侧的 LSB 读取(Intel,little-endian 机器),这是 0x41bb999a 或者实际上是 1102813594。

    然而,通常整数和浮点数存储在相同的字节中。根据您访问联合的方式,您将获得这些字节的整数或浮点解释。同样,内存空间的大小取决于实现,尽管它通常是与某个固定边界对齐的最大组成部分。

    为什么在您(或我的)案例中具有这样的价值?您应该阅读有关浮点数表示的信息(查找 ieee 754)

    【讨论】:

    • 嗯,你的意思可能不是“最大的组成部分”,而是最严格的。
    • @rogue:根据标准——“联合体的大小足以容纳其最大的成员”
    • iirc,来自 k&r,“虽然机器不同,但对于每台机器,都有一个最严格的类型:如果最严格的类型可以存储在特定地址,那么所有其他类型也可能是。” -- 但我想你是对的,因为标准总是正确的,无论哪种方式 + 1。
    • @rogue,你说的是对齐,所以你们俩都是对的。联合应与其所有成员正确对齐,通常由最严格的成员定义,并且对于最大的成员来说应该足够大。
    【解决方案2】:

    结果取决于编译器的实现,但对于大多数 x86 编译器,float 和 int 的大小相同。维基百科有一个很好的 32 位浮点布局图 http://en.wikipedia.org/wiki/Single_precision_floating-point_format,可以帮助解释 1102813594

    如果将 int 打印为十六进制值,将更容易计算出来。

    printf("%x\n", tst.i);
    

    【讨论】:

      【解决方案3】:

      使用联合,两个变量都存储在相同的内存位置。浮点数以 IEEE 格式存储(不记得标准编号,您可以查看[编辑:正如其他人指出的,IEEE 754])。但是,它将是一个二进制补码归一化(尾数始终在 0 和 10 之间,指数可以是任何值)浮点数。

      您正在获取该数字的前 4 个字节(再次,您可以查看浮点数占用的 16 位或 32 位中的哪些位,不记得了)。所以它基本上没有任何意义,它作为 int 没有用。也就是说,除非您知道为什么要这样做,但通常浮点和整数组合并不是很有用。

      而且,不,我不认为它是由实现定义的。我相信标准规定了浮点数的格式。

      【讨论】:

      • C++ 标准不强制要求符合 IEEE-754 的 FP 表示——但鼓励使用 std::numeric_limits::is_iec559 成员(相当于 IEEE-754)。此外,非规范化数字也是有效的。
      • 你可能比我记得更清楚。谢谢。 C 语言也一样吗?
      【解决方案4】:

      在联合中,成员将共享相同的内存。这样我们就可以将浮点值作为整数值。

      浮点数格式将不同于整数存储。这样我们就可以理解使用联合的区别。

      例如: 如果我将 12 个整数值存储在(32 位)中。我们可以得到这 12 个值作为浮点格式。

      它将存储为有符号(1 位)、指数(8 位)和有效精度(23 位)。

      【讨论】:

        【解决方案5】:

        我编写了一个小程序,它显示了将 32 位浮点数的位模式保存为 32 位整数时会发生什么。它为您提供与您正在经历的完全相同的输出:

        #include <iostream>
        
        int main()
        {
            float f = 23.45;
            int x = *reinterpret_cast<int*>(&f);
        
            std::cout << x; // 1102813594
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-12-21
          • 1970-01-01
          • 2014-11-05
          • 1970-01-01
          • 1970-01-01
          • 2018-08-29
          • 1970-01-01
          • 2019-07-02
          相关资源
          最近更新 更多