简体   繁体   English

C++ | 从 int 转换为 double(使用指针)

[英]C++ | Casting from int to double (with pointers)

int var = 8;
int* ptr = &var;
double* ptr2 = (double*) &var;


cout << "The int pointer points to the value: " << * ptr << "\n The Double pointer points to the value: " << *ptr2 << endl;

std::cin.get();

As you can see above, I wrote a super simple program while messing around with pointers (and a little bit of casting), which I'm just learning about.正如你在上面看到的,我写了一个超级简单的程序,同时搞乱了指针(和一点点转换),我只是在学习。 The program compiles and runs fine.该程序编译并运行良好。

The thing I'm confused about is that the *ptr outputs 8 as expected but the *ptr2 outputs -9.2559592117432085e+61.我感到困惑的是 *ptr 按预期输出 8 但 *ptr2 输出 -9.2559592117432085e+61。

When I go to the memory window in the debugger and go to the memory address that's pointed to by both of the pointers, the value stored there is 8, as expected. When I go to the memory window in the debugger and go to the memory address that's pointed to by both of the pointers, the value stored there is 8, as expected. What's up with the value that ptr2 outputs? ptr2 输出的值是怎么回事?

Thanks for reading and any clarifications.感谢您的阅读和任何澄清。

As others commented in the post, it is undefined behavior so the compiler can take any action at this point to print any value, even zero or infinite.正如其他人在帖子中评论的那样,这是未定义的行为,因此编译器此时可以采取任何操作来打印任何值,甚至为零或无限。

In this specific case, the compiler is actually doing the bare minimum, or perhaps nothing.在这种特定情况下,编译器实际上是在做最少的事情,或者什么也不做。 I reverse compiled your code with a union:我使用联合反向编译了您的代码:

#include <cstdint>
#include <cstdio>
union  DoubleUnion {
    double dval;
    uint32_t uval[2];
};

int main() {
    DoubleUnion uv;
    uv.dval = -9.2559592117432085e+61;
    printf( "%g %08x %08x\n", uv.dval, uv.uval[0], uv.uval[1] );
    return 0;
}

So basically I am placing a double and two 32-bit integers sharing the same space in memory.所以基本上我在 memory 中放置了一个共享相同空间的双精度和两个 32 位整数。 I then retrofit your printed number inside that double and check what the integers are.然后我 retrofit 你在那个 double 中打印的数字并检查整数是什么。 The result is this Compiler explorer link结果是这个编译器资源管理器链接

Program stdout
-9.25596e+61 00000008 cccccccc

So basically the first 4 bytes are exactly what you input, an eight.所以基本上前 4 个字节正是你输入的内容,一个 8。 The remaining 4 bytes are 0xcccccccc which is pretty much garbage, what was there after the integer, probably in the stack.剩下的 4 个字节是 0xcccccccc,这几乎是垃圾,在 integer 之后有什么,可能在堆栈中。

You can obtain the same result with the following (but incorrect) code:您可以使用以下(但不正确的)代码获得相同的结果:

#include <cstdint>
#include <cstdio>
int main() {
    double value = -9.2559592117432085e+61;
    uint32_t* ptr = (uint32_t*)&value;
    printf( "%g %08x %08x\n", value, ptr[0], ptr[1] );
    return 0;
}

Compiler explorer link编译器资源管理器链接

UPDATE I though you'd find interesting unpacking the double.更新我虽然你会发现打开双重包装很有趣。

#include <cstdint>
#include <cstdio>
#include <cmath>

int main() {
    struct [[gnu::packed]] Double {
        uint64_t mantissa: 52;
        uint32_t exponent: 11;
        uint32_t sign: 1;
    };
    union DoubleUnion {
        Double fields;
        double value;
        uint64_t uval;
    };
    DoubleUnion du;
    du.value = -9.2559592117432085e+61;
    printf( "Raw values: Double:%g Int:%16lx Sign:%d Exp2:%d Man:%ld\n", 
        du.value, du.uval, du.fields.sign, du.fields.exponent, du.fields.mantissa );

    int64_t mantissa = int64_t(du.fields.mantissa) | (int64_t(1) << 52);
    mantissa = (du.fields.sign) != 0 ? -mantissa : mantissa;
    int32_t exponent = int32_t(du.fields.exponent) - 1075;
    double dval = double( mantissa ) * pow(2,exponent);
    printf("Parsed values: Mantissa:%ld Exponent(2):%d Double:%g\n", mantissa, exponent, dval );

    return 0;
}

Godbolt link螺栓链接

This prints这打印

Program stdout
Raw values: Double:-9.25596e+61 Int:cccccccc00000008 Sign:1 Exp2:1228 Man:3602876265922568
Parsed values: Mantissa:-8106475893293064 Exponent(2):153 Double:-9.25596e+61

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM