如下面的代码所示,我尝试使用不同的方法将位从长longnum
复制到两个双精度d1
和d2
:指针投射+解除引用和/和按位分别和。
# 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
的大小,双倍的最大大小,在我看来,这是一个巨大的数字,实际上是两个双打的合理输出。
答案 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