所以以下将大端转换为小端
uint32_t ntoh32(uint32_t v)
{
return (v << 24)
| ((v & 0x0000ff00) << 8)
| ((v & 0x00ff0000) >> 8)
| (v >> 24);
}
的工作原理。喜欢魅力。
我从大端文件中读取4个字节到char v[4]
并将其作为
ntoh32 (* reinterpret_cast<uint32_t *> (v))
不起作用 - 因为我的编译器(VS 2005)在我进行投射时会自动将大端字符[4]转换为小端uint32_t。
AFAIK,这种自动转换不可移植,所以我使用
uint32_t ntoh_4b(char v[])
{
uint32_t a = 0;
a |= (unsigned char)v[0];
a <<= 8;
a |= (unsigned char)v[1];
a <<= 8;
a |= (unsigned char)v[2];
a <<= 8;
a |= (unsigned char)v[3];
return a;
}
是的(unsigned char)
是必要的。
是的,这是狗慢。
必须有更好的方法。有谁?
答案 0 :(得分:2)
更好的方法,恕我直言,正在使用htonl
和ntohl
函数。如果你想要真正便携,你不能想到“转换为小端”。相反,你应该考虑“转换为主机端”。这就是ntohl
的用途,如果您的输入肯定是一个大端(这就是网络标准)。
现在,如果你单独读取你的字节,你可以把它们读作无符号长(在二进制模式下) - 这应该给你一个大端长,然后你可以将它转换成你需要的任何东西 - 如果你需要的话主持人,然后是ntohl
。
答案 1 :(得分:0)
uint32_t ntoh_4b(char v[])
{
return ( (uint32_t)(unsigned char)v[0] << 24 )
| ( (uint32_t)(unsigned char)v[1] << 16 )
| ( (uint32_t)(unsigned char)v[2] << 8 )
| ( (uint32_t)(unsigned char)v[3] );
}
答案 2 :(得分:0)
(将此作为保留缩进的单独答案)
试验台......
union {
char a[4];
uint32_t i;
} t;
t.i = 0xaabbccdd;
uint32_t v;
for (uint32_t i = 0; i < -1; ++i)
{
//v = ntohl (t.i); (1)
//v = ntoh32 (t.i); (2)
//v = ntoh_4b (t.a); (3)
}
反汇编ntoh32 ......
movl %edi, -4(%rbp)
movl -4(%rbp), %eax
movl %eax, %edx
sall $24, %edx
movl -4(%rbp), %eax
andl $65280, %eax
sall $8, %eax
orl %eax, %edx
movl -4(%rbp), %eax
andl $16711680, %eax
shrl $8, %eax
orl %eax, %edx
movl -4(%rbp), %eax
shrl $24, %eax
orl %edx, %eax
leave
反汇编ntoh_4b ......
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
movzbl (%rax), %eax
movzbl %al, %eax
movl %eax, %edx
sall $24, %edx
movq -8(%rbp), %rax
addq $1, %rax
movzbl (%rax), %eax
movzbl %al, %eax
sall $16, %eax
orl %eax, %edx
movq -8(%rbp), %rax
addq $2, %rax
movzbl (%rax), %eax
movzbl %al, %eax
sall $8, %eax
orl %eax, %edx
movq -8(%rbp), %rax
addq $3, %rax
movzbl (%rax), %eax
movzbl %al, %eax
orl %edx, %eax
leave
最后,结果。我已经为C库ntohl
提供了时间来提供比较基准
//v = ntohl (t.i); (1)
real 0m35.030s
user 0m34.739s
sys 0m0.245s
//v = ntoh32 (t.i); (2)
real 0m36.272s
user 0m36.070s
sys 0m0.115s
//v = ntoh_4b (t.a); (3)
real 0m40.162s
user 0m40.013s
sys 0m0.097s