原创 指针不完全手册

2008-12-5 22:19 3652 6 6 分类: MCU/ 嵌入式
指针定义:c语言的一种基本数据类型,地位等同于char ,int,等;这种数据类型的变量总是存放一个内存单元地址。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


2、指针的特性:指针具有指向性,即指向某一数据实体。


3、指针变量:用指针数据类型定义的变量,其内容总是一个内存单元地址或NULL。指针变量本身也占有一定的内存单元,占几个字节跟此指针变量的类型有关,最多3字节,最少1字节。若此变量存放A数据实体的内存单元地址,我们称此指针变量指向A数据实体


4、指针变量的三个要素:、所指的对象类型、、对象位于的存储空间、、指针变量自己位于的存储空间;


每一指针总具有这三个要素,只不过有的要素明确定义决定,有的要素隐含定义决定,有的要素程序运行时才决定。


5、指针变量的类型:


根据三要素定义与否指针可分为三种类型:一般指针、基于存储器指针、抽象指针,其中要素3不影响指针类型,只影响指针变量本身存储区域。


、一般指针(Generic Pointers):要素1明确定义的,要素2未定义;同标准C语言的指针。


此类指针变量总占3个字节,第一字节表明所指对象的存储器类型(对象位于的存储空间),存储器类型编码(第一字节内容)0x00idata/data/bdata;0x01xdata;0xfepdata;0xffcode;第二字节存放所指对象的内存单元地址的高位字节,第三字节存放所指对象的内存单元地址的低位字节。


程序运行时,才能决定他指向哪个存储区域的对象;因此可以访问8052的所有存储空间。定义好之后未使用之前,他不指向任何单元,使用时赋给他xdata的地址它就指向xdata区的对象(二三字节均为有效值),赋给他data的地址它就指向data区的对象(二字节为00,三字节为有效值)。


例:char *p;  //定义


char xdata x;


int data y;


p = &x;   //p 指向 xdata 区


p = (char *)&y    //p 指向 data区 ,&y指向整数,所指对象类型不同,必须强制转换,


、基于存储器指针(Memory-specific pointers)要素1、2明确定义的;属keil的扩展定义,我们比较常用。


此类指针变量占1-2个字节,均存放所指对象的内存单元地址。基于idata/data/pdata时占1字节,基于xdata/code时占2字节。


所指对象的存储区域是编译期间决定的,程序运行期间不会改变,因此生成代码短于一般指针,运行速度较快,但应用缺乏灵活性。


例:char xdata  *p;   //定义


char xdata x;


int data y;


p = &x;   //p 指向 xdata 区


p = (char *)&y    //p 还指向 xdata区 &y指向整数,所指对象类型不同,必须强制转换,


、抽象指针(Abstract pointer)要素1、2未明确定义的指针或一个具体数值;我们不常用。


此类指针所指对象的类型及对象的存储空间都是NULL。


此类指针一般用来产生绝对调用或用来访问某存储区域的任意绝对地址。使用时一般是把抽象指针强制类型转换为别的类型指针。


例:void  *p; //抽象指针定义


char xdata  *px;  //定义基于存储器指针


char c;


 


应用:


 c =  *((char xdata *)0xff00);


//绝对访问xdata区的地址为0xff00单元。换句话说0xff00是一个抽象指针,被强制类型转化为指向xdata区的char 类型。再把它的对象赋给c


 


px = *((char xdata * xdata *)0x4000);


//绝对访问xdata区的地址为0x4000单元。换句话说0x4000是一个抽象指针,被强制类型转化为指向xdata区的char xdata * 类型。char xdata *也是一个指针,指向位于xdata区的char 类型,把char xdata *这个指针变量赋给px.


 


px = ((char xdata * xdata *)0x4000)[1];


//绝对访问xdata区的地址为0x4002,0x4003单元。换句话说0x4000是一个抽象指针,被强制类型转化为指向xdata区的char xdata * 类型。char xdata *也是一个指针,指向位于xdata区的char 类型,因为后者指向xdata 区,所以占连续两个字节。 现在访问以0x4000为起点的第二个元素,把第二个元素的内容赋给px。第一个元素占00,01两个单元,所以,第二个元素占02,03两个单元。这与<absacc.h>中的绝对访问整数的道理是一样的。


<absacc.h>的定义如下:(以下这段英文来自keil的帮助文件)


#define XWORD ((unsigned int volatile xdata*) 0)


You may use this macro in your programs as follows:


rval = XWORD [2];


XWORD [2] = 57;


to read or write the contents of the word in external data memory at address 0004h (2 × sizeof (unsigned int) = 4).


 


i = ((int(code*)(void))0xff00)();


//不带参数执行从0xff00开始的函数,函数返回值是一个整数,把返回值赋给I。换句话说0xff00是一个抽象指针,被强制类型转化为函数指针。


 


i = ((int(code*)(unsigned char, int))0xff00)(a,b);


//带参数a,b执行从0xff00开始的函数,形式参数的类型为unsigned char 和int;;a,b 为实参;函数返回值是一个整数,把返回值赋给I。换句话说0xff00是一个抽象指针,被强制类型转化为函数指针。好多人想了很久的方法!


 


也可以用一般指针做绝对地址访问,方法如下:


char *p;  //定义一般指针


char data c;


p = (char *) 0x50003L;//p 指向code区的0x0003单元


c = * p       //绝对访问code区的0x0003单元



char *p;  //定义一般指针


char data c;


p = 0x50003l;//p 指向code区的0x0003单元,默认强制类型转换。


c = * p   //绝对访问code区的0x0003单元


其中0x5000L的意思是5赋给一般指针的第一字节,(5会自动编译为 0xff送第一字节,为什么要送5,而不直接送0xff,可能是为了与早期版本兼容的原因(谁查到确切原因请告诉我。Data 送 4;pdata 送 3;xdata 送 2;code  送 5);这就是为什么马忠梅的书与徐爱军的书讲到指针编码时有冲突的原因;早期弗兰克林的c51<asbacc.h>的宏就是如下定义的#define  XBYTE (unsigned char *)0x20000L)。)0003赋给二三字节


6、指针类型的转换


大多数库函数的参数为一般指针,而我们经常定义基于基于存储器指针,因此需要相互转化。指针类型的转换上面的例子已涉及到一些,下面主要论述以下一般指针与基于存储器指针的相互转化。(以下这段英文来自keil的帮助文件)


、generic * to code * The offset section (2 bytes) of the generic pointer is used.


、generic * to xdata * The offset section (2 bytes) of the generic pointer is used.


、generic * to data * The low-order byte of the generic pointer offset is used,The high-order byte is discarded.


、generic * to idata * The low-order byte of the generic pointer offset is used,The high-order byte is discarded.


、generic * to pdata * The low-order byte of the generic pointer offset is used,The high-order byte is discarded.


 


、code * to generic * The memory type of the generic pointer is set to 0xFF for code.The 2-byte offset of the code * is used.


、xdata * to generic * The memory type of the generic pointer is set to 0x01 for xdata.The 2-byte offset of the xdata * is used.


、data * to generic * The 1-byte offset of the idata * / data * is converted to an unsigned int and used as the offset.


、idata * to generic * The memory type of the generic pointer is set to 0x00 for idata / data.


、pdata * to generic * The memory type of the generic pointer is set to 0xFE for pdata.The 1-byte offset of the pdata * is converted to an unsigned int andused as the offset.

文章评论0条评论)

登录后参与讨论
我要评论
0
6
关闭 站长推荐上一条 /2 下一条