Frage

Ich arbeite an einer Implementierung des memcache Protokolls, das an einigen Stellen, 64 Bit Integer-Wert verwendet. Diese Werte müssen in „Netzwerk-Byte-Reihenfolge“ gespeichert werden.

Ich wünschte, es einige uint64_t htonll(uint64_t value) Funktion war die Änderung zu tun, aber leider, wenn es vorhanden ist, konnte ich es nicht finden.

So habe ich 1 oder 2 Fragen:

  • Gibt es eine portable (Windows, Linux, AIX) Standardfunktion, dies zu tun?
  • Wenn es keine solche Funktion ist, wie würden Sie es umsetzen?

Ich habe eine grundlegende Implementierung im Auge, aber ich weiß nicht, wie die endianness zur Compile-Zeit zu überprüfen, den Code portabel zu machen. So Ihre Hilfe ist mehr als willkommen hier;)

Danke.


Hier ist die letzte Lösung, die ich geschrieben habe, dank Brian Lösung.

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;
    }
}
War es hilfreich?

Lösung

Sie suchen wahrscheinlich für bswap_64 ich denke, es ziemlich überall unterstützt wird, aber ich würde es nicht Standard nennen.

Sie können leicht die endianness überprüfen, indem Sie einen int mit einem Wert von 1 zu schaffen, Casting-Adresse Ihres int der als char* und überprüfen Sie den Wert des ersten Bytes.

Zum Beispiel:

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

Mit diesem Wissen können Sie auch eine einfache Funktion machen, die den Austausch der Fall ist.


Sie können auch immer Boost verwenden, die Endian-Makros enthält die tragbare Cross-Plattform sind.

Andere Tipps

#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))

Der Test (1 == htonl (1)) bestimmt einfach (zur Laufzeit leider), wenn die Hardware-Architektur Requres tauschen Byte. Es gibt keine tragbaren Möglichkeiten zur Compile-Zeit zu bestimmen, was die Architektur ist, so dass wir auf der Verwendung greifen „htonl“, die als tragbar ist, wie es in dieser Situation bekommt. Wenn Byte-Swapping benötigt wird, dann tauschen wir 32 Bits gleichzeitig mit htonl (Erinnerung an die zwei 32-Bit-Worte als auch zu tauschen).


Hier ist ein weiterer Weg, um die Swap durchzuführen, die über die meisten Compiler tragbar ist und Betriebssysteme, einschließlich AIX, BSD-Systeme, Linux und Solaris.

#if __BIG_ENDIAN__
# define htonll(x) (x)
# define ntohll(x) (x)
#else
# define htonll(x) ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
# define ntohll(x) ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
#endif

Der wichtige Teil ist die Verwendung __BIG_ENDIAN__ oder __LITTLE_ENDIAN__; und nicht __BYTE_ORDER__, __ORDER_BIG_ENDIAN__ oder __ORDER_LITTLE_ENDIAN__. Einige Compiler und Betriebssysteme fehlen __BYTE_ORDER__ und Freunde.

Sie können mit uint64_t htobe64(uint64_t host_64bits) versuchen & uint64_t be64toh(uint64_t big_endian_64bits) für umgekehrt.

Dies scheint Arbeit in C; habe ich etwas falsch gemacht?

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;
    }
}

Um den Overhead des reduzieren „wenn num == ...“ Verwenden Sie die Pre-Prozessor definiert:

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#else
#endif

EDIT: die Kombination der beiden (verwendet Brians Code):

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

Achtung: ungetesteten Code! Bitte Test vor der Anwendung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top