主机字节序

概念-什么是字节序

计算机中程序解析内存中的多字节数据时需要确定低地址存放低位(小端字节序),还是高地址存放低位(大端字节序),实际操作中不同的计算机并没有采用一致的处理方式,这就会造成同样的一段内存内容在被解释为数字时,会是完全不用的2个数。例如:在内存中同样存储2个字节数据,采用不同的解析方式得到的数值是不一样的,比如内存中存放

addr+0 | 0x01

addr+1 | 0x02

小端字节序解释为:0x0201

大端字节序解释为:0x0102

这种情况下,需要2个主机交换信息时,如果需要解释多字节数值,就会出现不一致的问题,为了解决这个问题大家达成了一个约定,默认在网上传输的数据采用大端字节序(即网络字节序),在发送端发送多字节数据时使用hton转换为大端字节序,在数据接收端接收到多字节数据时使用ntoh转换为本地字节序,从而避免因为字节序不一致导致的数据一致性问题。

转换

数据转换原理分析:

源数据:
0x0102030405060708
大端主机内存数据:
addr+0 | 0x01 |
addr+1 | 0x02 |
addr+2 | 0x03 |
addr+3 | 0x04 |
addr+4 | 0x05 |
addr+5 | 0x06 |
addr+6 | 0x07 |
addr+7 | 0x08 |
小端主机内存数据:
addr+0 | 0x08 |
addr+1 | 0x07 |
addr+2 | 0x06 |
addr+3 | 0x05 |
addr+4 | 0x04 |
addr+5 | 0x03 |
addr+6 | 0x02 |
addr+7 | 0x01 |

假设收到的数据为大端字节序存储的0x0102030405060708,本机使用字节序为小端字节序。
方法1:

#直接使用64位的转换函数把大端字节序数据转为小端字节序。
be64toh
转换后内存数据:
addr+0 | 08 |
addr+1 | 07 |
addr+2 | 06 |
addr+3 | 05 |
addr+4 | 04 |
addr+5 | 03 |
addr+6 | 02 |
addr+7 | 01 |

方法2:

#把64位的数据分为低32位和高32位数据分别使用be32toh后组合为完整的64位数据。

be32toh(p32[0])<<32 | be32toh(p32[1])
内存数据:
addr+0 | 0x01 |
addr+1 | 0x02 |
addr+2 | 0x03 |
addr+3 | 0x04 |
解析为数值:0x04030201 ---- be32toh ----> 0x01020304
addr+4 | 0x05 |
addr+5 | 0x06 |
addr+6 | 0x07 |
addr+7 | 0x08 |
解析为数值:0x08070605 ---- be32toh ----> 0x05060708

0x01020304 << 32 | 0x05060708
0x0102030405060708
转换后内存数据:
addr+0 | 08 |
addr+1 | 07 |
addr+2 | 06 |
addr+3 | 05 |
addr+4 | 04 |
addr+5 | 03 |
addr+6 | 02 |
addr+7 | 01 |

网络程序常用转换代码:

#include <arpa/inet.h>
#include <stdint.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);

其它程序常用转换代码:

#define _BSD_SOURCE             /* See feature_test_macros(7) */
#include <endian.h>
#include <stdint.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);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值