c - 与 long 复制的位不同的两个 double 打印不同

标签 c pointers casting bit-manipulation type-punning

如下面的代码所示,我试图将位从一个 long longnum 复制到两个 double ,d1d2,使用不同的方法:分别是指针转换 + 取消引用和“按位与”。

# include <stdio.h>

int main(void) {
    long longnum = 0xDDDDDDDDDDDDDDDD;
    double d1 = *((double*)(&longnum));
    double d2 = longnum & 0xFFFFFFFFFFFFFFFF;

    printf("%ld\n\n",longnum);
    printf("%lf\n\n",d1);
    printf("%lf\n",d2);
    return 0;
}

问题是两个 double 的打印方式不同,如下面的输出所示。

-2459565876494606883

-1456815990147462891125136942359339382185244158826619267593931664968442323048246672764155341958241671875972237215762610409185128240974392406835200.000000

15987178197214945280.000000

考虑到 DBL_MAX 的大小,一个 double 的最大大小,在我看来,它是一个巨大的数字,实际上是打印的两个 double 的合理输出。

最佳答案

double d2 = longnum & 0xFFFFFFFFFFFFFFFF;

& 掩码不做任何事情。一个数字与全 1 的 AND 运算是相同的数字。上面的行与:

double d2 = longnum;

该行没有进行任何重新解释。相反,它将 d2 设置为最接近代表 longnum 中值的 double。值(value)将是相似的;位模式将完全不同。

完成您想要做的事情的最佳方式是与 union 合作。 union 是执行的最佳方式type punning .

union {
     long l;
     double d;
} u;

u.l = longnum;
printf("%f\n\n", u.d);

像处理 d1 那样使用指针在技术上会调用未定义的行为。这是一个常见的习语,在实践中可能会很好地工作,但应该避免使用指针进行类型双关。

关于c - 与 long 复制的位不同的两个 double 打印不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40224463/

相关文章:

C++:指向包含子类的类的父指针

c++ - 指向 POD 结构的 C/C++ 指针也指向第一个结构成员

c++ - C 中的指针和继承 - 转换问题?

c++ - 为什么这段代码有内存泄漏?

c - 为什么在指针算术之前要强制转换为 (char *)? (container_of() 内部结构)

c - 警告 : cast to pointer from integer of different size

从基于源的索引转换为基于目标的索引

捕获分段违规并继续生活

创建ip网络数据包

c++ - C/C++ 中的#include 是多余的吗?