73

私は、ある時点で 64 ビットの整数値を使用する memcache プロトコルの実装に取り​​組んでいます。これらの値は、「ネットワーク バイト オーダー」で格納する必要があります。

変更を行う機能がuint64_t htonll(uint64_t value)あればいいのですが、残念ながら、存在する場合は見つかりませんでした。

だから私は1つまたは2つの質問があります:

  • これを行うための移植可能な (Windows、Linux、AIX) 標準機能はありますか?
  • そのような機能がない場合、どのように実装しますか?

基本的な実装を念頭に置いていますが、コンパイル時にエンディアンをチェックしてコードを移植可能にする方法がわかりません。だからあなたの助けはここで大歓迎です;)

ありがとうございました。


ブライアンのソリューションのおかげで、これが私が書いた最終的なソリューションです。

uint64_t htonll(uint64_t value)
{
    // The answer is 42
    static const int num = 42;

    // Check the endianness
    if (*reinterpret_cast<const char*>(&num) == num)
    {
        const uint32_t high_part = htonl(static_cast<uint32_t>(value >> 32));
        const uint32_t low_part = htonl(static_cast<uint32_t>(value & 0xFFFFFFFFLL));

        return (static_cast<uint64_t>(low_part) << 32) | high_part;
    } else
    {
        return value;
    }
}
4

7 に答える 7

19

おそらくbswap_64どこでもサポートされていると思いますが、標準とは呼びません。

値が 1 の int を作成し、int のアドレスを としてキャストしchar*、最初のバイトの値を確認することで、エンディアンを簡単に確認できます。

例えば:

int num = 42;
if(*(char *)&num == 42)
{
   //Little Endian
}
else
{
   //Big Endian
} 

これを知っていれば、スワッピングを行う単純な関数を作成することもできます。


また、移植可能なクロスプラットフォームであるエンディアン マクロを含む boost を常に使用することもできます。

于 2010-06-11T12:14:10.203 に答える
5

これはCで機能するようです。私は何か間違ったことをしましたか?

uint64_t htonll(uint64_t value) {
    int num = 42;
    if (*(char *)&num == 42) {
        uint32_t high_part = htonl((uint32_t)(value >> 32));
        uint32_t low_part = htonl((uint32_t)(value & 0xFFFFFFFFLL));
        return (((uint64_t)low_part) << 32) | high_part;
    } else {
        return value;
    }
}
于 2011-05-08T16:47:26.613 に答える
1

「if num == ...」のオーバーヘッドを削減するには、プリプロセッサ定義を使用します。

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#else
#endif
于 2014-06-12T13:27:28.027 に答える
-3

編集:2つを組み合わせる(ブライアンのコードを使用):

uint64_t htonll(uint64_t value)
{
     int num = 42;
     if(*(char *)&num == 42)
          return (htonl(value & 0xFFFFFFFF) << 32LL) | htonl(value >> 32);
     else 
          return value;
}

警告:テストされていないコード!使用する前にテストしてください。

于 2010-06-11T12:26:59.150 に答える