linux下的字节序问题总结

1. 字节顺序概念

字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端、大端两种字节顺序

大端对齐:内存的低地址位存放着高位数据;

小端对齐:内存的低地址位存放着低位数据;

举个例子,内存中两个连续字节中的数据为0x12 0x34,表示一个short,如果是大端对齐,这个数为0x1234;如果是小端对齐,则这个数为0x3412。


2. 测试

在我的开发机器上(linux2.6.16)上,经过测试,为小端对齐,转化为网络字节序之后,为大端对齐。

测试程序很简单:

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

int main()
{
        int16_t x = 1;
        if(*(char*)&x == 1)
                printf("little endian\n");
        else
                printf("big endian\n");

        int16_t y = ntohs(x);
        if(*(char*)&y == 1)
                printf("net little endian\n");
        else
                printf("net big endian\n");
}

3. linux api接口

网络字节序与本地字节序的转化,glibc提供了4个接口,man的结果如下:

BYTEORDER(3)		   Linux Programmer's Manual		  BYTEORDER(3)

NAME
       htonl,  htons,  ntohl,  ntohs - convert values between host and network
       byte order

SYNOPSIS
       #include <arpa/inet.h>

       uint32_t htonl(uint32_t hostlong);

       uint16_t htons(uint16_t hostshort);

       uint32_t ntohl(uint32_t netlong);

       uint16_t ntohs(uint16_t netshort);

DESCRIPTION
       The htonl() function converts the unsigned integer hostlong  from  host
       byte order to network byte order.

       The htons() function converts the unsigned short integer hostshort from
       host byte order to network byte order.

       The ntohl() function converts the unsigned integer netlong from network
       byte order to host byte order.

       The  ntohs() function converts the unsigned short integer netshort from
       network byte order to host byte order.

       On the i386 the host  byte  order  is  Least  Significant  Byte	first,
       whereas	the  network byte order, as used on the Internet, is Most Sig-
       nificant Byte first.

Glibc还提供了一组接口,直接转化本地字节序到大端或者小端对齐。(man查看的结果是glibc2.9之后开始支持的,我这边的机器上还没有)

ENDIAN(3)		   Linux Programmer's Manual		     ENDIAN(3)

NAME
       htobe16, htole16, be16toh, le16toh, htobe32, htole32, be32toh, le32toh,
       htobe64, htole64, be64toh, le64toh - convert values  between  host  and
       big-/little-endian byte order

SYNOPSIS
       #define _BSD_SOURCE	       /* See feature_test_macros(7) */
       #include <endian.h>

       uint16_t htobe16(uint16_t host_16bits);
       uint16_t htole16(uint16_t host_16bits);
       uint16_t be16toh(uint16_t big_endian_16bits);
       uint16_t le16toh(uint16_t little_endian_16bits);

       uint32_t htobe32(uint32_t host_32bits);
       uint32_t htole32(uint32_t host_32bits);
       uint32_t be32toh(uint32_t big_endian_32bits);
       uint32_t le32toh(uint32_t little_endian_32bits);

       uint64_t htobe64(uint64_t host_64bits);
       uint64_t htole64(uint64_t host_64bits);
       uint64_t be64toh(uint64_t big_endian_64bits);
       uint64_t le64toh(uint64_t little_endian_64bits);

4. 64位整型,本地与网络字节序的转化

如果是int64_t或者uint64_t,没有ntoh系列接口支持,只能通过htobe64这种接口来实现本地字节序到网络字节序的转换(从2中的测试中,可以得到网络字节序为大端对齐)。

如果glibc的版本不支持htobe系列的接口,那么只能自己写转换程序了,一个简单的转换程序如下:

uint64_t htonll(uint64_t v) {
    union { uint32_t lv[2]; uint64_t llv; } u;
    u.lv[0] = htonl(v >> 32);
    u.lv[1] = htonl(v & 0xFFFFFFFFULL);
    return u.llv;
}

uint64_t ntohll(uint64_t v) {
    union { uint32_t lv[2]; uint64_t llv; } u;
    u.llv = v;
    return ((uint64_t)ntohl(u.lv[0]) << 32) | (uint64_t)ntohl(u.lv[1]);
}

5. 参考文章

http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c

http://cpp.ezbty.org/import_doc/linux_manpage/be64toh.3.html

http://www.unix.com/man-page/Linux/3/ntohl/

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值