我对这个问题Swap bits in c++ for a double
的回答有一个大问题然而,这个问题或多或少是我搜索的内容: 我从网络收到一个双,我想在我的机器上正确编码。
在我收到int
的情况下,我使用ntohl
执行此代码:
int * piData = reinterpret_cast<int*>((void*)pData);
//manage endianness of incomming network data
unsigned long ulValue = ntohl(*piData);
int iValue = static_cast<int>(ulValue);
但是在我收到double
的情况下,我不知道该怎么做。
问题的答案建议:
template <typename T>
void swap_endian(T& pX)
{
char& raw = reinterpret_cast<char&>(pX);
std::reverse(&raw, &raw + sizeof(T));
}
但是,如果我引用this site:
The ntohl() function converts the unsigned integer netlong from network byte order to host byte order.
When the two byte orders are different, this means the endian-ness of the data will be changed. When the two byte orders are the same, the data will not be changed.
相反,@ GManNickG对问题的回答始终使用std::reverse
进行反转。
考虑到这个答案是假的,我错了吗? (在使用ntohl
建议的尽管未在OP问题的标题中准确说明的结束的网络管理程度)。
最后:我应该将double
分成4个字节的两个部分,并在这两个部分上应用ntohl
功能吗?还有更多的经典解决方案吗?
在C host to network double?中也存在这个有趣的问题,但它限制为32位值。答案说,由于架构差异,双打应该转换为字符串......我也会使用音频样本,我是否真的考虑将所有样本转换为数据库中的字符串? (双打来自我通过网络查询的数据库)
答案 0 :(得分:2)
如果您的双打是IEEE 754格式,那么您应该相对正常。现在你必须将它们的64位分成两个32位,然后以big-endian顺序传输它们(这是网络顺序);
怎么样:
void send_double(double d) {
long int i64 = *((reinterpret_cast<int *>)(&d)); /* Ugly, but works */
int hiword = htonl(static_cast<int>(i64 >> 32));
send(hiword);
int loword = htonl(static_cast<int>(i64));
send(loword);
}
double recv_double() {
int hiword = ntohl(recv_int());
int loword = ntohl(recv_int());
long int i64 = (((static_cast<long int>) hiword) << 32) | loword;
return *((reinterpret_cast<double *>(&i64));
}
答案 1 :(得分:1)
假设您有一个编译时选项来确定字节顺序:
#if BIG_ENDIAN
template <typename T>
void swap_endian(T& pX)
{
// Don't need to do anything here...
}
#else
template <typename T>
void swap_endian(T& pX)
{
char& raw = reinterpret_cast<char&>(pX);
std::reverse(&raw, &raw + sizeof(T));
}
#endif
当然,另一个选择是不要在网络上发送double
- 考虑到它不能保证与IEEE-754兼容 - 有些机器使用其他浮点格式...例如,字符串可以更好地工作......
答案 2 :(得分:1)
我无法让JohnKällén代码在我的机器上运行。此外,将double转换为字节(8位,1个字符)可能更有用:
template<typename T>
string to_byte_string(const T& v)
{
char* begin_ = reinterpret_cast<char*>(v);
return string(begin_, begin_ + sizeof(T));
}
template<typename T>
T from_byte_string(std::string& s)
{
assert(s.size() == sizeof(T) && "Wrong Type Cast");
return *(reinterpret_cast<T*>(&s[0]));
}
此代码也适用于使用POD类型的结构。
如果你真的希望双重作为两个整数
double d;
int* data = reinterpret_cast<int*>(&d);
int first = data[0];
int second = data[1];
最后,long int
并不总是64位整数(我必须使用long long int
在我的机器上创建64位int)。