从物理内存中理解C51指针

data区范围

data区为内RAM低128字节,地址0x00~0x7F
idata区为内RAM全部256字节,地址0x00~0xFF
pdata区为外RAM低256字节,地址0x0000~0x00FF
xdata区为外RAM全部65536字节,地址0x0000~0xFFFF
code区为程序空间全部65536字节,地址0x0000~0xFFFF

指针变量的值

指针变量也是一个变量,相较普通变量存放的是数据值,指针变量存放的是其他变量的地址值。

#include 	"header.h"

//定义一个变量放在data区,并指定地址为0x33
data unsigned char 	var_data 	_at_ 0x33;
idata unsigned char var_idata 	_at_ 0x88;
pdata unsigned char var_pdata 	_at_ 0x0011;
xdata unsigned char var_xdata 	_at_ 0x0222;
code unsigned char 	var_code 	_at_ 0x4444;

//定义一个指针,该变量实际在内存中占3个字节:[指向类型][地址H][地址L]
//以下变量均可指向任何区域,为方便区分而命名
unsigned char * ptr_data;
unsigned char * ptr_idata;
unsigned char * ptr_pdata;
unsigned char * ptr_xdata;
unsigned char * ptr_code;

void main()
{
	PowerInit();
	
	ptr_data = &var_data;
	//在内存中的值为: 00 00 33
	ptr_idata = &var_idata;
	//在内存中的值为: 00 00 88
	ptr_pdata = &var_pdata;
	//在内存中的值为: FE 00 11
	ptr_xdata = &var_xdata;
	//在内存中的值为: 01 02 22
	ptr_code = &var_code;
	//在内存中的值为: FF 44 44
	
	while(1);
}

仿真结果如下:
在这里插入图片描述

固定指向区域的指针

#include 	"header.h"

//定义一个变量放在data区,并指定地址为0x31
data unsigned char var_data 	_at_ 0x33;
idata unsigned char var_idata 	_at_ 0x88;
pdata unsigned char var_pdata 	_at_ 0x0011;
xdata unsigned char var_xdata 	_at_ 0x0222;
code unsigned char var_code 	_at_ 0x4444;

//声明地址指向data区,在内存中占1个字节:[地址]
unsigned char data * ptr_data;
//声明地址指向idata区,在内存中占1个字节:[地址]
unsigned char idata * ptr_idata;
//声明地址指向pdata区,在内存中占1个字节:[地址]
unsigned char pdata * ptr_pdata;
//声明地址指向xdata区,在内存中占2个字节:[地址H][地址L]
unsigned char xdata * ptr_xdata;
//声明地址指向code区,在内存中占2个字节:[地址H][地址L]
unsigned char code * ptr_code;

void main()
{
	PowerInit();
	
	ptr_data = &var_data;
	//在内存中的值为: 33
	ptr_idata = &var_idata;
	//在内存中的值为: 88
	ptr_pdata = &var_pdata;
	//在内存中的值为: 11
	ptr_xdata = &var_xdata;
	//在内存中的值为: 02 22
	ptr_code = &var_code;
	//在内存中的值为: 44 44
	
	/**
	* 注意:对于指针声明指向data区,同样可以用于指向idata高区;
	* ptr_data = &var_idata;//该为合法赋值
	* 以下等均为非法赋值,产生warning C259: '=': pointer: different mspace;
	* ptr_idata = &var_pdata;
	* ptr_pdata = &var_xdata;
	* ptr_xdata = &var_code;
	**/
	
	while(1);
}

仿真结果如下:
在这里插入图片描述
声明指针的指向地址后可以减小指针变量所占用的空间,但此时必须注意只能指向声明的区域。

指针变量存放位置

以上均省略了指针变量的位置,编译器会根据实际情况放在idata区或xdata区。
在上面示例中,对于指向xdata区的指针,可以认为(unsigned char xdata *)为一个整体,如果要定义指针变量本身的存放区域,可以在 (unsigned char xdata *)前后添加区域关键词。例如

//声明地址指向xdata区,指针变量本身存放在data区,以下两种声明方式相同
data unsigned char xdata * ptr;//或
unsigned char xdata * data ptr;

//在上面基础上进一步指定ptr的存放位置为data区的0x70处
data unsigned char xdata * ptr 	_at_ 0x70;//或
unsigned char xdata * data ptr 	_at_ 0x70;

指针赋值

xdata unsigned char var _at_ 0x0000;

unsigned char * ptr;
unsigned char xdata * ptr1;

//ptr未声明指向区域只能以下两种方式赋值
ptr = &var;//或
ptr = (unsigned char xdata *)0x0000;
//ptr1已声明指向区域,除以上两种方式.还可以直接赋地址值
ptr1 = 0x0000;

指针指向的数据类型

#include 	"header.h"

//定义指针指向xdata区
unsigned char xdata * ptr1;
unsigned int xdata * ptr2;
unsigned long xdata * ptr3;

void main()
{
	unsigned char i;
	PowerInit();
	
	//ptr1已声明指向区域,可以直接赋地址值
	ptr1 = 0x0000;
	for(i=0;i<4;i++){
		*ptr1 = 1;//ptr1操作的是一个8位变量
		ptr1++;
	}
	ptr2 = 0x0010;
	for(i=0;i<4;i++){
		*ptr2 = 2;//ptr2操作的是一个16位变量
		ptr2++;
	}	
	ptr3 = 0x0020;
	for(i=0;i<4;i++){
		*ptr3 = 3;//ptr3操作的是一个32位变量
		ptr3++;
	}
	
	while(1);
}

仿真结果如下:
在这里插入图片描述

总结

最常见的指针声明就是
unsigend char *ptr;
该指针为通用指针,可以指向任何区域,如
ptr = &var_idata;
ptr = &var_xdata;
ptr = &var_code;
此时的ptr在内存中占三个字节,[指向类型][地址H][地址L]。

想节省内存空间并提高程序效率可以定义专用指针,如
unsigend char pdata *ptr;
unsigend char xdata *ptr;
此时ptr在内存中根据地址大小分配1或2个字节。

想进一步提高程序运行效率,可以定义先变在data区,在定义指针在data区,如
data unsigned char var;
data unsigned char data * ptr;
ptr = &var;

指针声明中的unsigned char等类型,表示指针指向的数据是什么类型,即指针操作的数据的类型,即(*ptr)的类型。

Over!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值