51单片机大端小端问题~

6a47246d0d570f4eba30b6a1b0607a1c.png

问题

先看一段代码

//说明:uint32_t数据类型为4byte无符号整数,其他类型依此类推
uint32_t a = 0;
uint16_t b = 0x1223;
uint8_t *ptr = NULL;


ptr = (uint8_t  *)&b;
memcpy((uint8_t *)&a, ptr, sizeof(b));


printf("a = 0x%x\r\n",a);

这样写有没有问题?

这段代码运行结果是什么?

是 a = 0x1223 不?

在linux平台、一些WIFI模组+freeRTOS平台运行结果都是 0x1223,

在keil_C51单片机平台运行结果是 0x12230000。

进一步增加代码,加log打印。

uint32_t a = 0;
uint16_t b = 0x1223;
uint8_t *ptr = NULL;
uint32_t x = 0x12345678;    /*305414896 */
uint8_t *xp = (uint8_t *)&x;


printf("x = %d\r\n",x);
pritnf("xp[0]:%x\r\n xp[1]:%x\r\n xp[2]:%x\r\n xp[3]:%x\r\n", xp[0],xp[1],xp[2],xp[3]);


printf("sizefo short =%d sizeof int =%d\r\n",sizefo(uint16_t), sizeof(uint32_t));
ptr = (uint8_t  *)&b;
memcpy((uint8_t *)&a, ptr, sizeof(b));


printf("short b= 0x%x int a = 0x%x\r\n",b,a);

keil_C51运行结果:

9778b9a2304324aa9030904b9b712e36.png

linux 64位 运行结果:

227ea0ffe7e88d480aae7f04ba51d2fd.png

从打印log看到,在keil_C51环境中,

数据0x12345678,从地址地位到高位的排列顺序是:12、34、56、78,

低地址存着高字节数据,是大端存储模式,如下:


12

34

56

78

而linux环境中数据从低位到高位的排列顺序是:78、56、34、12,

低地址存着低字节数据,是小端存储模式,如下:


78

56

34

12

而memcpy函数是不管你大端小端,他只负责把源地址的数据复制到目的地址,你传进来参数告诉我复制多少字节,就复制多少字节。

ptr 以及 (uint8_t*)&a中分别是b 和a的 起始地址,把b中数据从低地址开始copy给a 的地址。

在keil_C51中,b中数据内存中存储排列为:


12

23

拷贝后,a中存储排列为:


12

23

00

00

在keilC51中,编译器用大端模式来处理上面的数据,那就等同于12是数据的最高字节,因此这个数是 0x12230000.

在linux环境中,b中数据存储排列为:


23

12

拷贝后,a 的存储排列为:


23

12

00

00

按小端模式来处理上面数据,则23是一个数的 最低字节,因此这个数是0x00001223.

没想到吧?51单片机居然是大端模式。上面那样的代码相信我们都写过,从来没出错,是因为我们用的平台大多是小端模式,很少遇到大端模式的。

总结

小端模式数据可以取地址把数据拷贝到另一个数的地址,数值不会变,

大端模式不能这样随意拷贝,拷贝后需要进行高低字节交换。

延伸

上文说的是keil_C51,51单片机是8位的,无所谓大端小端,由编译的工具链进行处理,

查到一份文档说明,在keil中,多字节数据被当成大端处理,在IAR8051中,多字节的数则是被当成小端来处理的。

如下图,

5b53a410dca780968f10424499dba44e.png

47b819c6014315965301e3437feb1c1e.png

1.浅谈传感器市场的发展趋势~

2.目前全球MCU的现状~

3.芯片缺货实情难判断,有MCU厂已进入对峙期~

4.【喂到嘴边了的模块】超级嵌入式系统“性能/时间”工具箱~

5.国产32位MCU未来要怎样发展?

6.做嵌入式软件开发提高代码编译速度的几种方法~

ce6c89579a03c8518946790c04f6c398.gif

免责声明:本文系网络转载,版权归原作者所有。如涉及作品版权问题,请与我们联系,我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值