

51编译器把所有的指针都统一成3字节,大概是为了统一计算。但是51里所有的寻址确实最多只要16字节就搞定了,我猜多出来的那个字节可能是最初设计C51的人预留出来的吧。。。。
正常51的寻址是:
data,idata,pdata 关键字修饰的变量地址是8位即一个字节。
xdata,code 关键字修饰的变量地址是16位即两个字节。
但是无论用什么关键字修饰指针,其都占用3个字节大小。对任何取值行为得到的sizeof的值也是3。
在keil4调试的时候,可以观察到所有的xdata类型的地址长度确实是3字节,但是高字节总是0。我尝试在工程设置中将外部RAM的起始地址设置成0xFFFF以后,结果想当然的失败了(51的外部RAM、ROM扩展只有16条地址线)。我也有想过指针的最高字节可能储存了变量的类型,但是实验结果表明无论是char 、int、还是unsigned int,最高字节还是0。这真是一个神奇的第3字节。看看有谁能挖到为什么。
这也告诉我们用C51编程使用指针是比较浪费内存的。

又做了实验,指针的最高字节确实代表了类型,不过是代表了地址类型。
最高字节 | 地址类型 |
0x00 | data、idata |
0x01 | xdata |
0xfe | pdata |
0xff |
code |
因此,由于最大16位的寻址能力加上51乱七八糟的寻址方式,其指针需要3字节空间。
比如将指针作为参数传递到子函数中时,如果无法判断地址类型,将无法获得正确的值。
没有用过AVR,PIC也不熟,不知道这两个系列的8位机是怎么样的。
比较熟悉的ARMcortex核心的STM32,因为其只有一个地址空间,FLASH、RAM、extRam、寄存器等等地址都在一个向量空间中,不存在地址的重叠,因此其指针无需额外的一个字节来标示地址类型,就是32位4字节的。

恩,解释的非常好,谢谢。
就是说,根据存储位置的不同,定义不同长度的指针,
存储类型与存储区关系
data ---> 可寻址片内ram(0-127)
bdata ---> 可位寻址的片内ram
idata ---> 可寻址片内ram,允许访问全部内部ram(0-255)
pdata ---> 分页寻址片外ram (MOVX @R0) (256 BYTE/页)
xdata ---> 可寻址片外ram (64k 地址范围FFFFH)
code ---> 程序存储区 (64k 地址范围)
可以看出,对于data/idata来说,8位的指针就可以了,但是xdata/code需要16位的指针才行。
回复
打赏帖 | |
---|---|
【STM32F769】AI之与本地deepseek对接被打赏50分 | |
Buck电路工作在CCM模式下电感电流的计算公式是什么?被打赏5分 | |
buck电路工作原理被打赏5分 | |
基于MSPM0L1306的MODBUS-RTU协议通讯实验被打赏100分 | |
我想要一部加热台+多合一调试工具被打赏18分 | |
每周了解几个硬件知识+485硬件知识分享被打赏10分 | |
【换取手持数字示波器】树莓派PICO调试器官方固件本地化部署实践被打赏24分 | |
【换取手持数字示波器】分享一个KEIL无法识别CMSIS-DAP调试器的解决办法被打赏20分 | |
【换取手持数字示波器】分享一个自制的ArduinoNano扩展板底板被打赏23分 | |
【换取手持示波器】树莓派PICOW网页烟花被打赏18分 |