关于KeilC51的指针

keil中的指针分为两种 , 一种是普通指针 , 兼容标准C语言的指针;另一种是我翻译成内存特殊指针(memory-specific pointers , 翻译的不好:>)
一、普通指针
普通指针的定义方式如下 ,  char * ptr; 跟标准C的定义方式一样 。这种指针占三个字节 。第一个字节是标识存储类型 , 是指针指向的变量的数据类型 。第二个字节是指针存储地址的高位字节 。第三个字节是指针存储地址的低位字节 。
普通指针默认存储在内部存储器data , 即片上RAM 。如果想指定指针的存储位置 , 可以在 * 后加上存储类型 , 如下面几种定义方式:
char*dataptr;//与char*ptr;等价 , 即默认的定义方式char*xdataptr;//指针存储在片外RAMchar*idataptr;//指针存储在idatachar*pdataptr;//指针存储在pdata由定义普通指针写的程序最终的代码较长 , 运行速度相对较慢 , 因为keil在编译的时候不知道这个指针将要指向的变量的数据类型 , 只有当程序执行的时候才能知道 , 所以编译器不能对这段代码进行优化 , 不过 , 这样做的优点是 , 此指针可以指向存储在任何位置的变量 。
二、内存特殊指针
内在特殊指针的定义方式为:
charxdata*ptr;这个指针存储的时候占的字节数是不一定的 , 占一个字节的变量类型为:idata , data ,  pdata ,  bdata 。占两个字节的变量类型为: code , xdata 。下图是我在keil上测试的时候截的图:
注意:
charxdata*ptr;这里定义的ptr所指向的变量存储在xdata中 , 即外部变量 , 这样的话指针变量ptr占两个字节 , 我们再定义一个外部变量 。
charxdatavariable1;ptr=&variable1;//这样是正确的 。这段程序中 , 变量variable1是存储在外部存储器中的 , 是最合适的 。
chardatavariable2;ptr=&variable2;变量variable2存储在片内存储器中 。一个字节的指针即可以够用 , 不过这样写程序也不算错 , 我试过keil也能运行 。像普通指针一样 , 定义内存特殊指针时也可以指定指针的存储位置 。
charxdata*dataptr;【关于KeilC51的指针】这个定义是说 , 定义了一个指向(存储在xdata)变量的一个(存储在data)的指针 。
内在特殊指针产生的代码可以经过编译器优化 , 运行速度较快 。因为指针指向变量的存储位置是知道的 , 所以编译器在编译的时候可以进行优化 。这样程序通过最简洁的方式去寻址 , 但是代价是降低了程序的灵活性 。
三、指针类型转换
编译器在适当的时候对指针的类型进行转换 。如进行参数传递的时候 。如下面这个外部函数声明printf中的形参ptr是一个变通指针 , 编译器为函数分配三个字节
externvoidprintf(char*ptr);chardata*ptr1;charxdata*ptr2;voiamain(void){printf(ptr1);//这样在参数传递的时候转换printf(ptr2);//未转换}
在第一个printf()调用中 , 实参是指向data , 占两个字节 。但是函数原型中形参是变通指针 , 占三个字节 。这样 , 参数传递的过程中将ptr1扩展了成三个字节再传递 。
注意:为了防止在传递参数的时候造成类似的指针类型错误 。在调用函数前 , 最好进行必要的外部函数声明(extern ...)或引用相应的头文件(#include ...)或者在函数调用填写参数的时候加上数据类型转换 。这样就有两种的转换方式 。
1、形参为普通类型 , 实参为内存特殊类型:补充第一个字节为相应的数据类型代码 。高位地址没有的补充第二字节为0
2、实参为内存特殊类型 , 形参为普通类型:截取相应的地址字节 。
四 , 由上面的说明我们可以看出 ,  , 只要我们写程序的时候在 * 两面都加上类型的标识符就可以了 。但是在使用的时候 * 两边都有类型标识 , 很容易记混 。
charxdata*dataptr;这是一个指向一个存储在xdata的数据类型为char的指针 , 但这个指针却存储在data中 。我是这样记的 , 与char在一起的xdata标识都是描述指针指向的变量的 。而跟指针在一起的标识是描述指针自己的 。


    推荐阅读