Keil C51中的指针

1. 一般指针(Generic Pointers)

Keil C51编译器支持两种指针类型:一般指针和基于存储器的指针,一般指针需要占用3个字节,基于存储器的指针只需要1~2个字节,一般指针具有较好的兼容性但运行速度较慢,基于存储器的指针具有较高的运行速度。

// 定义一般指针的方法
char *sptr;         / *char类型指针 */
int *numptr;      /* int型指针 */

一般指针在内存中占用3个字节,第一个字节存放该指针的存储器类型编码(由编译模式确定),第二个和第三个字节分别存放该指针的高位和低位地址偏移量。

存储器类型 idata/bdata/data xdata pdata code
编码值 0x00 0x01 oxFE 0xFF

一般指针可用于存取任何变量而不必考虑变量在8051单片机的存储器空间的位置,许多C51库函数采用了一般指针。函数可以通过一般指针来存取任何存储空间的数据。

//指定本身存储器空间位置的一般指针
char * xdata strptr;            /* 位于xdata空间的一般指针*/
int * data numptr;         /* 位于data空间的一般指针*/
long * idata varptr;   /* 位于idata空间的一般指针 */


char * ptr;          //指针占3字节,第一字节是标识存储类型,第二字节是存储地址高位字节,第三字节是低位字节
char * xdate ptr;    //指针存储在片外,xdate 是修饰ptr的
char * idate ptr;    //指针存储在片内,指针指向的数据可以是片内也可以是片外


2. 基于存储器的指针(Memory-Specific Pointers)

由于一般指针所指对象的存储空间位置只有在运行期间才能确定,编译器在编译期间无法优化存储方式,必须生成一般代码以保证能对任意空间的对象进行存取,因此一般指针所产生的代码运行速度较慢,如果希望加快运行速度则应采用基于存储器的指针。

基于存储器的指针所指对象具有明确的存储器空间,长度可为1个字节存储器类型为(idata,data,pdata)或2个字节(存储器类型为code、xdata)。

//基于存储器的指针
char data * str;      /* 指向data空间char型数据的指针 */
int xdata * num;   /* 指向xdata空间int型数据的指针 */
long code * pow;  /*指向code空间long型数据的指针*/


//定义基于存储器的指针时还可以指定指针本身的存储器空间位置。
char data * xdata str; /*指向data空间char类型数据的指针,指针本身在xdata空间*/
int xdata * data num; /*指向xdata空间int型数据的指针,指针本身在data空间*/
long code * idata pow; /*指向code空间long型数据的指针,指针本身在idata空间*/


char xdata * ptr;        //指针存储占字节不一定,根据变量存储类型不同不一样,xdata是修饰 *的,也就是数据存储在片外,此时ptr占两个字节
char idata * ptr;        //数据是片内,指针ptr只有一个字节,i
char xdata * date ptr;   //指针在片内,数据在片外xdata是和char 一起修饰数据的 

基于存储器的指针长度比一般指针短,可以节省存储器空间,运行速度快,但它所指对象具有确定的存储器空间,缺乏兼容性。

3. 指针类型转换

一般指针与基于存储器的指针可以相互转换,但容易出错。所以编程时最好对数据和对指针的修饰都要。

在某些函数调用中进行参数传递时需要采用一般指针,例如,C51的库函数printf()、sprintf()、gets()等便是如此,当传递的参数是基于存储器的指针时,若不特别指明,C51编译器会自动将其转换为一般指针。

如果采用基于存储器的指针作为自定义函数的参数,而程序中又没有给出该函数原型,则基于存储器的指针就自动转换为一般指针。

假如在调用函数时确实需要采用基于存储器的指针作为传递参数,那么指针的自动转换就可能导致错误,为避免这类错误,应该在程序的开始处用#include将函数原型说明文件包含进来,或者直接给出函数原型声明。

//函数中指针类型的转换
extern int printf (void *format, ...);
extern int myfunc (void code *p, int xdata *pq);

int xdata *px;
char code *fmt = "value = %d | %04XH\n";

void debug_print (void) 
 {
  printf (fmt, *px, *px);          /* fmt is converted */
  myfunc (fmt, px);                /* no conversions */
}

4. 指针的绝对地址赋值

char xdata * XROM;
XROM=(char xdata *)0xB012;    //指针XROM的值就是0xB012,(char xdata *)表示强制类型转换
*XROM='r';                    //给0xB012的地址内容赋值r
a=*((char xdata *)0xB012);    //等同于a=*XROM,此时a='r' 

你可能感兴趣的:(Keil C51中的指针)