7.5.2 存储器指针

存储器指针是指在声明指针时明确指定其存储类型,即声明该指针指向特定的存储区的变量类型。

1.存储器指针声明

在定义一般指针的同时说明指针的存储类型,其一般形式如下:

标识符关键字*指针变量名

其中,标识符为变量的类型,关键字表示变量的存储类型,示例如下。


char data*str;//定义指针str指向data区中char型变量

int xdata*pi;//定义指针pi指向外部RAM的int型变量


由于存储器的类型已经明确指定,因此存放这种指针时,只需存放其偏移量即可。对于idata、data、bdata和pdata存储类型只需1个字节,对于code和xdata存储类型只需要2个字节。

在定义存储器指针时,可将指针与其指向的变量定义在不同的存储区,示例如下。


int xdata*data pi;//定义指针pi指向外部RAM的int型变量


本例中,定义指针pow指向外部RAM的int型变量,但是指针pow本身存放在片内RAM中。这是较常用的声明方式,可以提高指针访问外部数据的效率。存储器指针的程序示例如下。


include<stdio.h>//头文件

include<reg51.h>

void main()//主函数

{

char data*pc;//定义指向data存储区中的char型变量的指针变量

int xdata*pi;//定义指向xdata存储区中的int型变量的指针变量

long code*pl;//定义指向code存储区中的long型变量的指针变量

char data dc=‘A’;//初始化

int xdata buf1[3]={‘A’,8,2008};

long code lx=2008;

pc=&dc;//赋值

pi=&buf1[1];

pl=&lx;

printf(“%c%d%ld\n”,pc,pi,*pl);//输出结果

}


该程序可以在KeilµVision3集成开发环境中运行,其结果如下。


A 8 2008


在本例中,首先定义存储器指针pc、pi和pl,接着分别对其进行初始化赋值,最后打印输出结果。由本例可以看出存储器指针只能指向指定存储区中的变量。

在C51程序中,如果要将存储器指针作为实参,传递给形参为一般指针的函数时,存储器指针将自动转化为一般指针类型。若不声明外部函数原型,存储器指针的自动转变类型可能会导致错误,因而在程序开头要用include说明所有函数原型,这样就可以强行改变指针类型。

2.指针存储类型与指针所指向的数据的存储类型

在使用存储器指针时,要注意指针存储类型与指针所指向的数据的存储类型是两个不同的概念,示例如下。


uchar xdata t[10];//数组t在xdata存储区占10个字节的内存空间(0x0000~0x0009)

uchar data*pt;

pt=t;


本例中,数组t存放在xdata存储区,访问外部xdata存储区需要两个字节来寻址64KB空间。而指针pt被定为data存储类型,所以编译器将其编译成指向内部data存储区的指针变量了。因此后面的赋值语句是错误的,但可采用如下的3种方法进行修改。

方法一,上面的语句可以改为如下形式。


uchar xdata t[10];

uchar xdata*data pt;

pt=t;


本例中,在内部RAM定义指针pt,其被定为指向xdata存储区的变量,而数组t存放在xdata存储区,这样就可以进行访问。这是效率最高的访问外部RAM的方法。

方法二,上面的语句可以改为如下形式。


uchar xdata t[10];

uchar xdata*xdata pt;

pt=t;


这种方式也是正确的,一般用在内RAM资源相对紧张,而且对效率要求不高的项目中,其访问效率不如前一种方法。如果将上面改为如下形式。


uchar xdata t[10];

uchar data*xdata pt;

pt=t;


这样方式也是错误的。这次是把指针pt分配到了外RAM区了。C51中一个指针变量最多占用3字节,对于没有声明指针指向存储空间类型的指针,系统编译代码时都强制加载一个字节的指针类型分辨值。

方法三,上面的语句可以改为如下形式。


uchar xdata t[10];

uchar*pt;

pt=t;


这是最直接最简单的指针变量声明,但其访问效率也最低,既把指针pt分配在外部RAM空间,又增加了指针类型的分辨值。

对于上面几种正确的访问方式,有的访问效率高,有的访问效率低。在实际编程中,要根据实际情况选择。一般来说,当单片机的内部RAM资源比较紧张时,建议将函数内部或程序段内部的局部变量存放在片内RAM,而尽量不要把全局变量声明在片内RAM中。