Я работаю над реализацией протокола кэш-памяти, который, в некоторых точках, использует целочисленные значения на 64 бита. Эти значения должны быть сохранены в "сетевом порядке байтов".
Мне жаль, что не было некоторых uint64_t htonll(uint64_t value)
функция, чтобы сделать изменение, но к сожалению, если это существует, я не мог бы найти его.
Таким образом, у меня есть 1 или 2 вопроса:
Я имею в виду базовое внедрение, но я не знаю, как проверить порядок байтов во время компиляции для создания кода портативным. Таким образом, Ваша справка является больше, чем приветствие здесь ;)
Спасибо.
Вот конечное решение, которое я записал благодаря решению Brian.
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;
}
}
Вы, вероятно, ищете bswap_64
Я думаю, что он поддерживается практически везде, но я бы не назвал его стандартным.
Вы можете легко проверить эндианальность, создав int со значением 1, приведя адрес вашего int как char*
и проверив значение первого байта.
Например:
int num = 42;
if(*(char *)&num == 42)
{
//Little Endian
}
else
{
//Big Endian
}
Зная это, вы также можете сделать простую функцию, которая выполняет обмен.
Вы также всегда можете использовать boost, который содержит макросы endian, переносимые на разные платформы.
РЕДАКТИРОВАТЬ: объединение двух (используется код Брайана):
uint64_t htonll(uint64_t value)
{
int num = 42;
if(*(char *)&num == 42)
return (htonl(value & 0xFFFFFFFF) << 32LL) | htonl(value >> 32);
else
return value;
}
Предупреждение: непроверенный код! Пожалуйста, проверьте перед использованием.