将双精度指针转换为整型指针

Converting a double pointer to an int pointer

本文关键字:指针 整型 转换 双精度      更新时间:2023-10-16

当我打印bd时,它们都持有相同的地址(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;
}

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

#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";
}

这显示了double存储在内存中的单个字节。得到的结果是:

0       0       0       0       0       0       14      40

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

当然,如果你把它打印成long long int,你会得到一个非零的结果(long long int至少需要64位)。同样,如果您在大端系统上执行此操作,则double1440字节可能存储在内存中的第一个字节,而不是最后一个字节,因此结果仍然是非零的。

底线是,在这种情况下,您的强制转换大致相当于reinterpret_cast。它不是将double 转换为int值,而是查看double占用的内存字节,并将它们解释为int

注意,上面的结果并不是真正需要的,你不能指望它发生在可移植代码中。是非常常见和广泛期望的(例如,在大多数具有IEEE浮点和32位int s的小端机器上)。

因为双精度体的表示格式与int完全不同(即使您假设它们具有相同的大小)。double使用浮点格式,而int不使用。用int指针寻址double是未定义的行为。

相关:陷阱表示。

编辑如果你是一个初学者,它可能看起来很奇怪,像int i = 3.14;的工作,即double被转换为int,但是指向double的指针不能用来表示/转换为int。这是因为在第一种情况下,编译器负责转换,并自动将3.14截断为3,然后将后者表示为int,即3。而3double表示在内存中看起来完全不同。

这段代码由于违反了严格的混叠规则而导致未定义的行为。

它也可能由于对齐冲突而导致UB,但我将在本文中假设它不会。

对象d的类型是double。但是您尝试通过类型为int的glvalue *b访问它的内存。这不是[basic.lval]/10:

中列出的允许的别名类型之一。

如果程序试图通过非下列类型的glvalue访问对象的存储值,则该行为是未定义的:

  • 对象的动态类型,
  • 对象动态类型的cv限定版本,
  • 与对象的动态类型相似的类型(定义见4.4),
  • 与对象的动态类型对应的有符号或无符号类型的类型,
  • 是动态类型的cv限定版本对应的有符号或无符号类型
  • 在其元素或非-中包含上述类型之一的聚合或联合类型静态数据成员(递归地包括子聚合的元素或非静态数据成员)或包含联合),
  • 是对象动态类型的基类类型(可能是cv限定的),
  • 一个char或unsigned char类型。