具有不同长度复制的位的两个双打以不同方式打印

时间:2016-10-24 17:48:43

标签: c pointers casting bit-manipulation type-punning

如下面的代码所示,我尝试使用不同的方法将位从长longnum复制到两个双精度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;
}

问题是两个双打都没有以相同的方式打印,如下面的输出所示。

-2459565876494606883

-1456815990147462891125136942359339382185244158826619267593931664968442323048246672764155341958241671875972237215762610409185128240974392406835200.000000

15987178197214945280.000000

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

2 个答案:

答案 0 :(得分:3)

double d2 = longnum & 0xFFFFFFFFFFFFFFFF;

&蒙版没有做任何事情。带有全1的AND编号是相同的编号。上面的行与:

没有什么不同
double d2 = longnum;

这条线没有做任何一点重新解释。相反,它会将d2设置为最接近double中值的longnum。价值相似;位模式将完全不同。

做你想要做的事情的最好方法是结合工会。工会是执行type punning的最佳方式。

union {
     long l;
     double d;
} u;

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

d1一样使用指针技术上会调用未定义的行为。这是一个常见的习惯用法,在实践中可能会很好用,但应该避免用指针打字。

答案 1 :(得分:0)

你的问题是

d1 = *((double*)(&longnum));

通过执行上述操作,您错误地从内存中获取内容,然后假设它是双精度格式。

如果您通过以下方式执行此操作:

d1 = (double) longnum;

然后内存空间longnum的内容(一个8字节整数)正确转换,然后存储在d1指向的位置的内存中正确存储。 然后d1的内容将是正确的。 建议你阅读关于“双精度浮点格式”的维基百科页面

浮点值(或双精度值)的值在内存中的存储方式与整数的存储方式不同。 https://en.wikipedia.org/wiki/Double-precision_floating-point_format