4

我对这个问题的答案有一个很大的问题在 c++ 中交换位以获得双倍

然而,这个问题或多或少是我要寻找的:我从网络收到一个双精度,我想在我的机器中正确编码它。


在我收到的情况下,我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));
}

但是,如果我引用这个网站

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 语言中还有一个有趣的问题,主机到网络双倍?,但它限制为 32 位值。答案说由于架构差异,双打应该转换为字符串......我还将使用音频样本,我是否真的应该考虑将所有样本转换为我的数据库中的字符串?(双打来自我通过网络查询的数据库)

4

4 回答 4

2

如果你的双打是 IEEE 754 格式,那你应该还可以。现在您必须将它们的 64 位分成两个 32 位的一半,然后以大端顺序(即网络顺序)传输它们;

怎么样:

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));
}
于 2013-02-26T01:03:40.203 回答
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 兼容 - 有些机器使用其他浮点格式......例如使用字符串会更好...

于 2013-02-26T01:03:59.190 回答
1

我无法让 John Källén 代码在我的机器上运行。此外,将双精度转换为字节(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 位整数)。

于 2015-08-27T22:02:27.970 回答
0

如果你想了解系统无字节序

只要#if __cplusplus > 201703L

#include <bit>
#include <iostream>

using namespace std;

int main()
{
    if constexpr (endian::native == endian::big)
        cout << "big-endian";
    else if constexpr (endian::native == endian::little)
        cout << "little-endian";
    else
        cout << "mixed-endian";
}

欲了解更多信息:https ://en.cppreference.com/w/cpp/types/endian

于 2021-12-08T02:09:14.837 回答