从unsigned int加倍[2]?

时间:2017-02-08 14:51:15

标签: c

我有一个64位数字,写成两个32位无条件的整数:unsigned int[2]unsigned int[0]是MSB,unsigned int[1]是LSB。如何将其转换为double

double d_from_u2(unsigned int*);

3 个答案:

答案 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)。