将双指针转换为int指针

rah*_*hul 0 c++ pointers type-punning

当我打印b并且d他们都持有相同的地址(地址a).那么为什么*b打印0*d打印5?

 void main() 
 {
    double a = 5.0;
    double *d = &a;
    int *b = (int*)d;
    int a1 = 10;
    cout << "Val of D : " << d << " Address of d :" << &d
         << " Value of *d :" << *d << endl;
    cout << "Val of B : " << b << " Address of B :" << &b
         << " Value of *b :" << *b << endl;
}
Run Code Online (Sandbox Code Playgroud)

Jer*_*fin 7

让我们对代码做一个小改动:

#include <iostream>

int main() {
    double a = 5.0;
    double *d = &a;
    char *b = (char *)&a;
    int a1 = 10;

    for (int i = 0; i < sizeof(double); i++)
        std::cout << std::hex << (int)b[i] << "\t";
}
Run Code Online (Sandbox Code Playgroud)

这向我们展示了double它们存储在内存中的各个字节.我得到的结果是:

0       0       0       0       0       0       14      40
Run Code Online (Sandbox Code Playgroud)

现在,如果你看看它的前四个字节,它们都是零.假设您int是两个或四个字节,当您尝试将该内存视为a时int,结果将为零,因为double的所有非零字节都存储在内存中,而不是您正在查看的部分.用它作为int.

当然,如果你把它作为一个long long int替代打印出来,你会得到一个非零结果(a long long int要求至少为64位).同样,如果你在big-endian系统上这样做,那么14它的40字节double可能会存储在内存中的第一个字节而不是最后一个字节,因此结果将再次为非零.

底线是,在这种情况下,你的演员大致相当于一个reinterpret_cast.它不是double 取值并将其转换为int值,而是查看占用的内存字节数double,并将它们解释为它们int.

请注意,上面的结果并不是真正需要的,您不能指望它在便携式代码中发生.尽管如此(例如,在大多数具有IEEE浮点和32位s的小端机器上),这非常普遍和广泛期望int的.


vso*_*tco 6

因为double以完全不同的格式表示int(即使你假设它们具有相同的大小).A double使用浮点格式,而int不是.double使用int指针寻址a 是未定义的行为.

相关:陷阱表示.

编辑 如果你是一个初学者,似乎很奇怪,像int i = 3.14;工作,即一个double转换为一个int,但是一个指针,double不能用于表示/转换为int.这是因为在第一种情况下,编译器负责转换,并自动截断3.14,3然后将后者表示为a int,即as 3.而外观的double表现3在记忆中完全不同.