我想知道以便携方式将整数转换为/从little-endian转换的推荐方法。
那有没有图书馆?
我们可以使用htonl and ntohl然后使用另一个big-endian(来自)little-endian转换,但效率不高。
答案 0 :(得分:1)
便携式方法是将位移和掩码用于适当大小的字符串。注意我说的是字符串,因为这是你需要关注字节序的唯一时间 - 在系统之间传输字节时。
如果你想避免不必要的转换(例如在小端架构上转换为little-endian),那么在编译时就没有完全可移植的方法。但您可以在运行时检查以动态选择转换函数集。
这样做的缺点是代码无法内联。以便携方式编写转换并使用模板或内联可能更有效。结合半便携式编译时检查,这与您一样好。
在编译时进一步阅读:Detecting Endianness。
答案 1 :(得分:1)
这是一个很好的问题。它促使我看看是否有任何方法可以使用constexpr表达式在编译时确定字节序。
事实证明,没有预处理器技巧,这是不可能的,因为在constexpr上下文中进行评估时,无法将整数转换为字节序列(通过强制转换或联合)。
然而事实证明,在gcc中,当使用-O2进行编译时,简单的运行时检查会被优化掉,所以这实际上是最有效的:
#include <cstdint>
#include <iostream>
constexpr bool is_little_endian()
{
union endian_tester {
std::uint16_t n;
std::uint8_t p[4];
};
constexpr endian_tester sample = {0x0102};
return sample.p[0] == 0x2;
}
template<class Int>
Int to_little_endian(Int in)
{
if (is_little_endian()) {
return in;
}
else {
Int out = 0;
std::uint8_t* p = reinterpret_cast<std::uint8_t*>(std::addressof(out));
for (std::size_t byte = 0 ; byte < sizeof(in) ; ++byte)
{
auto part = (in >> (byte * 8)) & 0xff;
*p++ = std::uint8_t(part);
}
return out;
}
}
int main()
{
auto x = to_little_endian(10);
std::cout << x << std::endl;
}
这是在intel(little-endian)平台上编译时的汇编程序输出:
main:
subq $8, %rsp
#
# here is the call to to_little_endian()
#
movl $10, %esi
#
# that was it - it's been completely optimised away
#
movl std::cout, %edi
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
movq %rax, %rdi
call std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
xorl %eax, %eax
addq $8, %rsp
ret