4

私はこの質問への答えに大きな問題を抱えています

それでも、この質問は多かれ少なかれ私が探しているものです。ネットワークから 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));
}

ただし、このサイトを引用すると、次のようになります。

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の質問のタイトルでは正確に述べられていませんでしたが、の使用が示唆するエンディアンのネットワーク管理の範囲で)。

最後に: mydoubleを 4 バイトの 2 つの部分に分割し、2 つの部分にntohl関数を適用する必要がありますか? もっと標準的な解決策はありますか?

Cには、ホストからネットワークへの二重の興味深い質問もありますか? 、ただし、32 ビット値に制限されます。そして答えは、アーキテクチャの違いにより、倍精度を文字列に変換する必要があると言っています...オーディオサンプルも扱うつもりですが、データベース内のすべてのサンプルを文字列に変換することを本当に検討する必要がありますか? ( double は、ネットワーク経由でクエリを実行するデータベースから取得されます)

4

4 に答える 4

2

ダブルスがIEEE754形式の場合は、比較的問題ないはずです。次に、64ビットを2つの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 のコードを自分のマシンで動作させることができませんでした。さらに、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 を 2 つの int として本当に必要な場合

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 に答える