通俗易懂说字节序,大小端,网络序和主机序

1. 什么是字节序

字节序:
顾名思义字节的顺序,
就是大于一个字节类型的数据在内存中的存放顺序

一个字节的数据没有顺序的问题了。
如: char 类型数据占1字节,没有字节序问题
但是 int 占4字节,故int类型数据在传输过程中就需要考虑字节序的问题。

1.1 为什么字符串不用转序

例子:

char acName[32];
memset(acName, 0, sizeof(acName));
strlcpy(acName, "hani", sizeof(acName));
不用转序传输到网络……
接收……

因为:

字符串中的每个字符如'h','a','n'等都是占一个字节。
就没有字节序的问题了。
而 int a = 4; //a占4个字节就涉及字节序了。

2. 什么是网络字节序

网络字节序:
TCP/IP各层协议将字节序定义为Big-Endian,
因此TCP/IP协议中使用的字节序通常称之为网络字节序。

	4个字节的32 bit值以下面的次序传输:
		高字节--------------------------------------低字节
	首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。
	这种传输次序称作大端字节序。

由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序

3. 什么是主机字节序

3.1 主机字节序

通常我们说的主机序(Host Order)就是遵循Little-Endian规则

就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。

3.2 大小端字节序

标准的Big-Endian和Little-Endian的定义如下:
  a) Little-Endian 小端
  就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
  
  b) Big-Endian 大端
  就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

4. 举例

数据: 0x1234 大小端传输:
在十进制中我们都说靠左边的是高位,靠右边的是低位,在其他进制也是如此。就拿 0x1234来说,从高位到低位的字节依次是0x12、0x34。
其中,地址 0x00 是低地址,0x01是高地址。

地址: 0x00  0x01
大端:  12  	 34
小端:  34    12

4.1 主机序代码例子说明

//定义
typedef struct stTest{
	……
	UINT            uiID;/*ID */
	UINT            uiLoadId;
	UINT            uiWhoisSum;
	UINT            uiFileWhoisSum;
	……
}

//赋值
stTest pstItem;
……
pstItem->uiID = XX_INVALID_INSTANCE_ID;	//(0xffffffff)
pstItem->uiLoadId = XX_FILELOAD_MAX;	//3
pstItem->uiWhoisSum = 0;
pstItem->uiFileWhoisSum = 2;

//看内存
(gdb) x /32x &pstItem->uiID
  //内存地址升高b0	    b1		b2		b3		b4		b5		b6		b7
0xfc62b0:       0xff    0xff    0xff    0xff    0x03    0x00    0x00    0x00
0xfc62b8:       0x00    0x00    0x00    0x00    0x02    0x00    0x00    0x00
0xfc62c0:       0x32    0x32    0x32    0x33    0x00    0x00    0x00    0x00
0xfc62c8:       0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
(gdb)

由此可以看出:uiLoadId 的值3,0x00 00 00 03低字节存放在低地址处,是小端序

5. 判断一个体系结构是 big-endian 还是 little-endian

5.1 简单方法:

直接打印代码中的大于一个字节的值即可:(如int类型值)
小端序:

//同上,看内存
//小端序设备
(gdb) x /32x &pstItem->uiID
//内存地址升高b0	    b1		b2		b3		b4		b5		b6		b7
0xfc62b0:       0xff    0xff    0xff    0xff    0x03    0x00    0x00    0x00
0xfc62b8:       0x00    0x00    0x00    0x00    0x02    0x00    0x00    0x00
0xfc62c0:       0x32    0x32    0x32    0x33    0x00    0x00    0x00    0x00
0xfc62c8:       0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
(gdb)

大端序:

//大端序设备
(gdb) x /32x &pstItem->uiID
0x12f70dfe0:     0xffffffff      0x00000003      0x00000000      0x00000000
0x12f70dff0:     0x32323200      0x00000000      0x00000000      0x00000000
……

5.2 复杂方法:

int x = 1;  /* 32位 二进制 00000000 00000000 00000000 00000001 */

/* 
* 内存地址方向:   高位  <--------------------> 低位
* little-endian 表示: 00000000 00000000 00000000 00000001
* big-endian 表示:    00000001 00000000 00000000 00000000
*/
if (*(char *) &x == 1)   /* 这里把int型转为char型, 相当于只取了int型的最低8bit */
	/* little-endian */
else
	/* big-endian */

5.3 一般来说:arm和x86架构是小端序,mips架构是大端序

https://www.cnblogs.com/straight/articles/7660889.html
https://blog.csdn.net/yusiguyuan/article/details/48222789/

6. 源码实现

通俗易懂说字节序,大小端,网络序和主机序(2)htonl和ntohl 源码实现
https://blog.csdn.net/lqy971966/article/details/106468789

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值