大小端以及网络序的区别

前言:
在处理网络通信数据时,除了按照协议的数据解析和打包,还会涉及到非单字节数据(16位或者32位)在内存中的存储方式,也就是所谓的大小端问题。

1 什么是大/小端?
参考百度百科解释:
大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。

小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。

2 测试方法
在进行测试之前,先思考以下几个问题:
(1)数据的高低字节很好理解,那内存的高低地址如何区分?
(2)在函数中定义多个局部数组变量,其数组的首地址是递减还是递增?单个数组内的元素的地址递减还是递增?栈区的生长方式是?
(3)如何使用联合体union来测试内存模式为大端还是小端?
(4)使用memcpy(dest,sour,length)是否需要注意大小端?

测试硬件平台:STM32F767NI

测试代码:

void fun_test()
{
    uint8_t msgbuffer[32];  //第1个数组变量
	uint8_t msgbuffer1[32]; //第2个数组变量,其首地址是高于还是低于第1个数组变量的首地址呢?
	uint8_t msgbuffer3[4]; //第3个数组变量,其首地址是高于还是低于第2个数组变量的首地址呢?

	union test_u{
		uint32_t value32;
		uint8_t value8[4]; //这个数组的4个内容值是按照什么方式来存储的?
	};
	union test_u test; //
	
	test.value32 = 0x12345678;
	memcpy(&msgbuffer3[0],&test.value32,sizeof(test.value32)); //msgbuffer3中的4个值是12/34/56/78怎样的顺序?
	
	/* 以下的printf 将揭晓答案 */
	printf("msgbuffer3[0] value: %x \n",msgbuffer3[0]);  //输出结果为78
	printf("msgbuffer3[1] value: %x \n",msgbuffer3[1]); //输出结果为56
	printf("msgbuffer3[2] value: %x \n",msgbuffer3[2]); //输出结果为34
	printf("msgbuffer3[3] value: %x \n",msgbuffer3[3]); //输出结果为12,这说明高字节存放在数组的高偏移中,那高偏移的地址是高地址吗?请看下面

	printf("msgbuffer[0] addr: %x \n",&msgbuffer[0]); //输出结果为0x20056980
	printf("msgbuffer[4] addr: %x \n",&msgbuffer[4]); //输出结果为0x20056984
	printf("msgbuffer[20] addr: %x \n",&msgbuffer[20]);//输出结果为0x20056994,这说明数组内的高偏移的地址就是高地址
	/* 重要 */
	printf("msgbuffer1[0] addr: %x \n",&msgbuffer1[0]);//输出结果为0x20056960(小于0x20056980),这说明先后定义的数组的首地址是递减的,这就说明了在函数中定义的局部变量是存放在栈区的,生长方式为向下生长。
	printf("msgbuffer1[4] addr: %x \n",&msgbuffer1[4]);//输出结果为0x20056964
	printf("msgbuffer1[20] addr: %x \n",&msgbuffer1[20]);//输出结果为0x20056974

	printf("test addr: %dx \n",&test);
	printf("test.value8[0] addr: %x \n",&test.value8[0]);//输出结果为0x20056958
	printf("test.value8[1] addr: %x \n",&test.value8[1]);//输出结果为0x20056959
	printf("test.value8[2] addr: %x \n",&test.value8[2]);//输出结果为0x2005695a
	printf("test.value8[3] addr: %x \n",&test.value8[3]);//输出结果为0x2005695b

	printf("test.value8[0] value: %x \n",test.value8[0]);//输出结果为78
	printf("test.value8[1] value: %x \n",test.value8[1]);//输出结果为56
	printf("test.value8[2] value: %x \n",test.value8[2]);//输出结果为34
	printf("test.value8[3] value: %x \n",test.value8[3]);//输出结果为12,高地址存放高字节,联合体说明该平台为小端模式
}

测试结果:

在这里插入图片描述
3 网络序
在网络或者串口传输时,一般定义先到的是高字节,后到的为低字节。在接受数据时,数组buffer[0]为高字节,但是buffer[0]又是低地址,也就是低地址存放高字节,这说明所谓的网络序,其实就是大端模式。

4 总结
当通信双方的存储方式不一样时,在发送打包/接收解析时均要注意大小端之间的转换,否则数据就会出现错乱。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值