【问题标题】:Is the type of variable stored somewhere? Where is it?变量的类型是否存储在某处?它在哪里?
【发布时间】:2021-10-20 21:39:12
【问题描述】:

例如,

float f = 2.4;
int n = f + 1;

n = 3

变量 f 在内存中是 0x4019999a, 所以我认为 f + 1 = 0x4019999a + 1 但计算机没有。 如何知道 f 是“浮动”?即使 f 在内存中只是 0x4019999a。 变量的类型是否存储在某个地方?

【问题讨论】:

标签: c compiler-construction typeinfo


【解决方案1】:

type 没有显式存储(在优化的生产可执行文件中;调试输出中包含各种额外信息)。

“那么如果没有存储类型,它怎么知道如何处理f = f + 1n = n + 1 不同?”我听到你问。 :-) 答案是编译器在编译时知道类型,并为这些操作输出不同的 CPU 指令。在f 的情况下,它输出处理浮点值的指令,但在n 的情况下,它输出处理二进制补码整数的指令。

【讨论】:

    【解决方案2】:

    不存储变量类型。编译器根据您编写的代码发出机器代码指令。

    在你的例子中:

    float f = 2.4;
    int n = f + 1;
    

    float2.4 正在转换为 int,其值为 21 被添加到整数值 2。结果是3f 在内存中的物理表示无关紧要。

    如果您想将1 添加到被视为无符号整数的f 的物理内存表示中,您需要:

    float f = 2.4f;
    unsigned n,m;
    
    memcpy(&n, &f, sizeof(n));
    m = n + 1;
    

    【讨论】:

      【解决方案3】:

      类型仅在翻译过程中很重要,此时编译器正在分析您的源代码并生成等效的机器代码。那是当诸如“一元*的操作数必须具有指针类型”和“+的操作数必须具有算术类型”和“函数调用中的参数类型和数量必须与函数声明匹配”等规则时被强制执行。

      类型信息未明确存储在生成的机器代码中。根据源代码中使用的类型,生成的机器代码将根据对象的大小以及是否为浮点数使用不同的操作码和寄存器。例如在 x86 上,当将两个单精度浮点数相加时,编译器会将指令 addss 添加到机器码中;两个32位的ints相加时,会加上指令addl

      所以我认为 f + 1 = 0x4019999a + 1 但计算机没有。

      int 不能存储小数值 - C 中的规则是,当您将浮点值分配给整数目标时,小数部分会被截断。 n不能存储3.4,只能存储3

      我把你上面的sn-p打包成一个完整的程序,编译一下1,然后查看生成的机器码。线条

      float f = 2.4;
      int n = f + 1;
      

      翻译如下:

      movss   LCPI0_0(%rip), %xmm0    ## xmm0 = mem[0],zero,zero,zero
      movss   LCPI0_1(%rip), %xmm1    ## xmm1 = mem[0],zero,zero,zero
      ...
      movss   %xmm1, -8(%rbp)
      addss   -8(%rbp), %xmm0
      cvttss2si   %xmm0, %eax
      movl    %eax, -12(%rbp)
      

      movss 指令将单精度浮点值从一个位置复制到另一个位置 - 在这种情况下,它将浮点值 2.41.0 复制到浮点寄存器 %xmm0%xmm1,分别。 %xmm1 (2.4) 中的值被复制到位置-8(%rpb),这是变量f 的空间。该值将添加到%xmm0 (1.0) 中的值。此时%xmm0 包含值3.4。然后通过cvttss2si 指令将该值转换为其等效整数 (3),并将结果存储在 32 位通用(即非浮点)寄存器%eax 中。然后将该结果复制到n (-12(%rbp))。

      请记住,浮点值和整数值具有完全不同的表示。 32位整数值1的二进制表示为0x00000001;单精度浮点值1.0 的二进制表示为0x3f800000


      1. Apple LLVM 版本 10.0.1 (clang-1001.0.46.4)
        目标:x86_64-apple-darwin18.6.0

      【讨论】:

        猜你喜欢
        • 2017-03-26
        • 2010-10-02
        • 2015-02-13
        • 2021-02-08
        • 2018-02-01
        • 2010-09-18
        • 2015-01-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多