![](/img/trans.png)
[英]Is it safe to pass a uint64_t containing a 32-bit value to an external function whose parameter is actually a uint32_t?
[英]Turn two uint32_t into a uint64_t, then turn back into a double based on the bit pattern not the value
交给我两个 uint32_t 的代码本质上是一个双精度,二进制将它切成两半,所以一半的字节在一个变量中,另一半在另一个变量中。
我的程序需要把它们拼接起来。
int x = 0b00111101110100011101110111110111;
int y = 0b11100111001100101010000110111001;
uint64_t int64 = (long long) x << 32 | y;
double d = static_cast<double> (int64);
这是我到目前为止所拥有的,它根本没有给出正确的 output。
它给出:1.84467e+19 它应该是:6.49999999999999952595094363798E-11
谢谢
对于C,你可以这样做:
const uint32_t x = 0x3DD1DDF7;
const uint32_t y = 0xE732A1B9;
const uint64_t z = ((uint64_t) x << 32) | y;
double d;
memcpy(&d, &z, sizeof d);
但我不确定,这里可能存在字节顺序问题,因为这段代码非常多毛。 我得到 6.5e-11 作为 output。
这有效:
unsigned int x = 0b00111101110100011101110111110111;
unsigned int y = 0b11100111001100101010000110111001; // Must be unsigned!
uint64_t int64 = ((long long) x << 32) | y; // Parentheses highly recommended for
// readability (but not strictly necessary)
double d = reinterpret_cast<double&> (int64); // Definitely not portable!
您的代码有两个问题:
y
被转换为long long
,这意味着高位字是0xFFFFFFFF
。 x
和y
应声明为unsigned
。static_cast
转换值,而不是位模式。 使用reinterpret_cast
保留位模式。 (正如 Mgetz 在评论中指出的那样,现在(自 C++20 起)有一种官方方法可以完成此操作: std::bit_cast
。这不依赖于未定义的行为,只要double
和int64
相同尺寸。)这段代码如何满足您的目的。 例子
#include <cstdio>
#include <cinttypes>
#include <type_traits>
#include <cstddef>
#include <iostream>
int main()
{
uint64_t tsc = 0xdeaddeadc0dec0de;
uint32_t MSB = *((uint32_t*)&tsc+1);
uint32_t LSB = *((uint32_t*)&tsc);
std::printf("low %x high %x \n", LSB,MSB);
uint64_t MLSB = 0;
*((uint32_t*)&MLSB) = LSB;
*((uint32_t*)&MLSB+1) = MSB;
std::printf("highlow %lx \n", MLSB);
uint64_t LMSB = 0;
*((uint32_t*)&LMSB+1) = LSB;
*((uint32_t*)&LMSB) = MSB;
std::printf("lowhigh %lx \n", LMSB);
}
解决你的问题
#include <cstdio>
#include <cinttypes>
#include <type_traits>
#include <cstddef>
#include <iostream>
int main()
{
int x = 0b01000000001101110000000000000000;
int y = 0b00000000000000000000000000000000;
uint64_t int64 = 0;
*((uint32_t*)&int64+1) = x;
*((uint32_t*)&int64) = y;
double d = *((double*)&int64);
std::printf("double d %e \n", d);
std::printf("int int64 %llx \n", int64);
x = 0b00111101110100011101110111110111;
y = 0b11100111001100101010000110111001;
*((uint32_t*)&int64+1) = x;
*((uint32_t*)&int64) = y;
d = *((double*)&int64);
std::printf("double d %e \n", d);
std::printf("int int64 %llx \n", int64);
}
结果
双 d 2.300000e+01
int int64 4037000000000000
双 d 6.500000e-11
int int64 3dd1ddf7e732a1b9
或者没有引用问题
#include <cstdio>
#include <cinttypes>
#include <type_traits>
#include <cstddef>
#include <iostream>
int main()
{
unsigned char x[] = {0b01000000,0b00110111,0b00000000,0b00000000};
unsigned char y[] = {0b00000000,0b00000000,0b00000000,0b00000000};
uint64_t int64 = 0;
*((unsigned char*)&int64+7) = x[0];
*((unsigned char*)&int64+6) = x[1];
*((unsigned char*)&int64+5) = x[2];
*((unsigned char*)&int64+4) = x[3];
*((unsigned char*)&int64+3) = y[0];
*((unsigned char*)&int64+2) = y[1];
*((unsigned char*)&int64+1) = y[2];
*((unsigned char*)&int64+0) = y[3];
double d =0;
*((unsigned char*)&d+7) = x[0];
*((unsigned char*)&d+6) = x[1];
*((unsigned char*)&d+5) = x[2];
*((unsigned char*)&d+4) = x[3];
*((unsigned char*)&d+3) = y[0];
*((unsigned char*)&d+2) = y[1];
*((unsigned char*)&d+1) = y[2];
*((unsigned char*)&d+0) = y[3];
//*((double*)&int64);
std::printf("double d %e \n", d);
std::printf("int int64 %lu \n", int64);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.