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źć.
- 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;
}
}
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.
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).
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;
}
}
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.
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
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.
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