Czy w C++jest jakaś "standardowa" funkcja htonl dla 64 bitowych liczb całkowitych?

Pracuję nad implementacją protokołu memcache, który w niektórych punktach używa 64-bitowych wartości całkowitych. Wartości te muszą być zapisane w "sieciowej kolejności bajtów".

Chciałbym, żeby była jakaś uint64_t htonll(uint64_t value) funkcja do zmiany, ale niestety, jeśli istnieje, nie mogłem jej znaleźć.

Więc mam 1 lub 2 pytania:
  • czy jest jakaś przenośna (Windows, Linux, AIX) standardowa funkcja do tego celu ?
  • Jeśli nie ma takiej funkcji, jak zaimplementowałbyś to ?

Mam na myśli podstawową implementację, ale nie wiem, jak sprawdzić endianness w czasie kompilacji, aby Kod był przenośny. Więc twoja pomoc jest tu mile widziana;)

Dziękuję.

Oto ostateczne rozwiązanie, które napisałem, dzięki rozwiązaniu Briana.

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;
    }
}
Author: ereOn, 2010-06-11

6 answers

Prawdopodobnie szukasz bswap_64 myślę, że jest obsługiwany prawie wszędzie, ale nie nazwałbym tego standardem.

Możesz łatwo sprawdzić endianness, tworząc int o wartości 1, podając adres int jako char* i sprawdzając wartość pierwszego bajtu.

Na przykład:

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

Wiedząc o tym, możesz również stworzyć prostą funkcję, która wykonuje zamianę.


Można również zawsze użyć boost, który zawiera makra endian, które są przenośna Platforma krzyżowa.

 17
Author: Brian R. Bondy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-11 12:23:18
#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))

Test(1==htonl (1)) po prostu określa (w czasie wykonywania niestety), czy architektura sprzętowa wymaga zamiany bajtów. Nie ma żadnych przenośnych sposobów, aby określić w czasie kompilacji, jaka jest architektura, więc uciekamy się do używania "htonl", który jest tak przenośny, jak w tej sytuacji. Jeśli wymagana jest zamiana bajtów, to zamieniamy 32 bity na raz za pomocą htonl (pamiętając o zamianie również dwóch 32 bitowych słów).

 14
Author: deltamind106,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-19 14:55:21

To chyba działa w C; czy zrobiłem coś złego?

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;
    }
}
 4
Author: pix0r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-08 16:47:26

Możesz spróbować z uint64_t htobe64(uint64_t host_64bits) & uint64_t be64toh(uint64_t big_endian_64bits) na vice-versa.

 4
Author: suresh m,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-23 04:00:16

Aby zmniejszyć napowietrzność " if num == ..." Użyj preprocesora definiuje:

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#else
#endif
 1
Author: user3734255,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-12 13:27:28

EDIT: połączenie dwóch (użyto kodu Briana):

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

Uwaga: nieprzetestowany kod! Proszę przetestować przed użyciem.

 -3
Author: Pavel Radzivilovsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-11 12:42:09