我有一个64位数字,写成两个32位无条件的整数:unsigned int[2]
。 unsigned int[0]
是MSB,unsigned int[1]
是LSB。如何将其转换为double
?
double d_from_u2(unsigned int*);
答案 0 :(得分:5)
memcpy
以正确的顺序从源数组到double
对象。例如。如果你想交换unsigned
部分
unsigned src[2] = { ... };
double dst;
assert(sizeof dst == sizeof src);
memcpy(&dst, &src[1], sizeof(unsigned));
memcpy((unsigned char *) &dst + sizeof(unsigned), &src[0], sizeof(unsigned));
当然,您始终可以将源对象和目标对象重新解释为unsigned char
的数组,并按照您希望的任何顺序逐字节复制它们
unsigned src[2] = { ... };
double dst;
unsigned char *src_bytes = (unsigned char *) src;
unsigned char *dst_bytes = (unsigned char *) &dst;
assert(sizeof dst == 8 && sizeof src == 8);
dst_bytes[0] = src_bytes[7];
dst_bytes[1] = src_bytes[6];
...
dst_bytes[7] = src_bytes[0];
(第二个例子并不等同于第一个例子。)
答案 1 :(得分:4)
有两种方法可以将两个整数的位复制到double
类型的对象中。
在最低级别,您可以将输入指针转换为[unsigned
] char *
,在返回的第一个字节处创建[unsigned
] char *
价值,并通过您选择的任何方式复制。这为您提供了根据需要调整字节顺序的所有机会 - 例如,尽管您的数组首先被排序为最重要的字,但这些字中的字节顺序可能不是您需要的
如果您需要首先将字节传输到double
最高有效字节,并且您不想依赖于机器字节顺序,则可以执行以下操作:
double d_from_u2(unsigned int *in) {
double result;
unsigned char *result_bytes = (unsigned char *) &result;
for (int i = 0; i < 4; i++) {
result_bytes[i] = in[0] >> (24 - 8 * i);
result_bytes[i + 4] = in[1] >> (24 - 8 * i);
}
return result;
}
使用算术(在这种情况下为移位)允许您独立于数字表示的细节操作输入的数值。
答案 2 :(得分:0)
这是一个无memcpy
但使用union
:
#include "stdio.h"
#include "stdint.h"
double d_from_u2(unsigned int* v) {
union {
int32_t x[2];
int64_t y;
} u = { .x = { v[1], v[0] }};
printf("%llu\n", u.y); // 1311768467463794450
return (double)u.y;
}
int main(void) {
int32_t x[2];
x[0] = 0x12345678;
x[1] = 0x9abcef12;
printf("%f\n", d_from_u2(x)); // 1311768467463794432.000000
return 0;
}
见demo。在初始化联合中的数组int32_t[2]
并使用int64_t
将其转换为double
。初始化的顺序取决于它运行的机器(小端或大端)或值的来源(首先是1)。