C签署的Endian转换

时间:2011-12-16 17:10:49

标签: c unix

我试图在big endian文件中写入带符号的整数值。

我正在使用此代码:

int32_t swap_int32( int32_t val )
{
    val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF ); 
    return (val << 16) | ((val >> 16) & 0xFFFF);
}

它可以正常负值,但我有一些正值的问题:

-5给了我:

$> hexdump OUTPUT
ff ff ff fb

哪个是正确的

但是1337给了我:

  $> hexdump OUTPUT
     00 00 05 39

而不是(预期)00 00 39 05。

无论如何都要对待这两种情况并获得正确的结果吗? 谢谢你。

4 个答案:

答案 0 :(得分:3)

使用htonl时有问题吗?

   #include <arpa/inet.h>

   uint32_t htonl(uint32_t hostlong);

字节中的值应该保持不变,所以即使你想要一个有符号的值,只要你把它读回一个有符号的类型,你就不需要签名,你就不应该丢失数据。 (正如mctylr所述,网络秩序是大端的。)

#include <arpa/inet.h>
#include <stdio.h>

int main(int argc, char** argv) {
  int32_t pos = 1337;
  int32_t neg = -123;
  printf("host-endian:  %d => 0x%08x  %d => 0x%08x \n", 
         pos, pos, neg, neg);

  uint32_t big_endian_pos = htonl(pos);
  uint32_t big_endian_neg = htonl(neg);

  printf("Big-endian:   %d => 0x%08x %d => 0x%08x \n", 
         pos, big_endian_pos, neg, big_endian_neg);

}

我的小端主机上的输出:

[tmp]$ gcc endian.c  && ./a.out 
host-endian:  1337 => 0x00000539  -123 => 0xffffff85 
Big-endian:   1337 => 0x39050000  -123 => 0x85ffffff 

答案 1 :(得分:1)

至少应该在你的功能中强制转换为“无符号”。

作为替代方案,您始终可以使用网络宏“htons()”(16位)和“htonl()”(32位)将主机转换为网络(big-endian)字节顺序。

答案 2 :(得分:0)

网络字节顺序是大端。

POSOX UNIX有htonl(),htons()和朋友可以满足您的需求。他们保证任何系统都有大端。

答案 3 :(得分:0)

在* BSD和Linux系统上,您可以在byteorder(9)小主机上使用bswap_32()功能,包括#include <sys/endian.h> /* other platforms may need: sys/param.h endian.h or byteswap.h */ #include <stdint.h> uint32_t in, out; out = bswap_32(in);

stdlib.h

在小端MS Windows系统上,{{1}}中包含endian,即使它不是标准版。

否则,可以在Internet上轻松找到各种_byteswap_ulong

和StackOverflow

  • 将C中的big endian转换为little endian {不使用提供的func} bit twiddling examples
  • 如何在C ++中的big-endian和little-endian值之间进行转换? 2182002
  • ASM 105252中快速的小端到大端转换 - 3个答案中有2个不是面向C#的