指针就是指变量或数据所在的存储区地址。如一个字符型的变量 STR 存放在内存单元DATA 区的 51H 这个地址中,那么 DATA 区的 51H 地址就是变量 STR 的指针。在 C 语言中指针是一个很重要的概念,正确有效的使用指针类型的数据,能更有效的表达复杂的数据结构,能更有效的使用数组或变量,能方便直接的处理内存或其它存储区。指针之所以能这么有效的操作数据,是因为无论程序的指令、常量、变量或特殊寄存器都要存放在内存单元或相应的存储区中,这些存储区是按字节来划分的,每一个存储单元都能用唯一的编号去读或写数据,这个编号就是常说的存储单元的地址,而读写这个编号的动作就叫做寻址,通过寻址就能访问到存储区中的任一个能访问的单元,而这个功能是变量或数组等是不可能代替的。C 语言也因此引入了指针类型的数据类型,专门用来确定其他类型数据的地址。用一个变量来存放另一个变量的地址,那么用来存放变量地址的变量称为“指针变量”。 如用变量 STRIP 来存放文章开头的 STR 变量的地址 51H,变量 STRIP 就是指针变量。下面用一个图表来说明变量的指针和指针变量两个不一样的概念。

  变量的指针就是变量的地址,用取地址运算符‘&’取得赋给指针变量。&STR 就是把变量 STR 的地址取得。用语句 STRIP = &STR 就能把所取得的 STR 指针存放在 STRIP 指针变量中。STRIP 的值就变为 51H。可见指针变量的内容是另一个变量的地址,地址所属的变量称为指针变量所指向的变量。

  要访问变量  STR  除了能用‘STR’这个变量名来访问之外,还能用变量地址来访问。方法是先用&STR 取变量地址并赋于 STRIP 指针变量,然后就能用*STRIP 来对 STR 进行访问了。‘*’是指针运算符,用它能取得指针变量所指向的地址的值。在上图中指针变量 STRIP 所指向的地址是 51H,而 51H 中的值是 40H,那么*STRIP 所得的值就是 40H。 使用指针变量之前也和使用其它类型的变量那样要求先定义变量,而且形式也相类似,一般的形式如下:

  数据类型    [存储器类型]    *    变量名;

unsigned char xdata * pi;      //指针会占用二字节,指针自身存放在编译器默认存储区,指向 xdata 存储区的 char 类型
unsigned char xdata * data pi; //除指针自身指定在 data 区,其它同上
int * pi; //定义为一般指针,指针自身存放在编译器默认存储区,占三个字节。 

  在定义形式中“数据类型”是指所定义的指针变量所指向的变量的类型。“存储器类型”是编译器编译时的一种扩展标识,它是可选的。在没有“存储器类型”选项时,则定义为一般指针,如有“存储器类型”选项时则定义为基于存储器的指针。限于 51 芯片的寻址范围,指针变量最大的值为 0xFFFF,这样就决定了一般指针在内存会占用 3 个字节,第一字节存放该指针存储器类型编码,后两个则存放该指针的高低位址。而基于存储器的指针因为不用识别存储器类型所以会占一或二个字节,idata,data,pdata 存储器指针占一个字节,code,xdata 则会占二个字节。由上可知,明确的定义指针,能节省存储器的开销,这在严格要求程序体积的项目中很有用处。

  指针的使用方法很多,限于篇幅以上只能对它做一些基础的介绍。下面用在讲述常量时的例程改动一下,用以说明指针的基本使用方法。

#include <AT89X51.H> //预处理文件里面定义了特殊寄存器的名称如 P1 口定义为 P1

void main(void)
{

    //定义花样数据,数据存放在片内 CODE 区中

    unsigned char code design[]={   0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,
                                    0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFF,
                                    0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,
                                    0xE7,0xDB,0xBD,0x7E,0xFF};

    unsigned int a;              //定义循环用的变量
    unsigned char b;
    unsigned char code * dsi;    //定义基于 CODE 区的指针

    do{
        dsi = &design[];        //取得数组第一个单元的地址
        ; b<; b++){
        }
    });

}

    ; a<; a++);    //延时一段时间
    P1 = *dsi;                 //从指针指向的地址取数据到 P1 口
    dsi++;    //指针加一, 

  为了能清楚的了解指针的工作原理,能使用 keil uv2 的软件仿真器查看各变量和存储器的值。编译程序并执行,然后打开变量窗口,如图。用单步执行,就能查到到指针的变量。如图中所示的是程序中循环执行到第二次,这个时候指针 dsi 指向 c:0x0004 这个地址,这个地址的值是 0xFE。在存储器窗口则能察看各地址单元的值。使用这种方法不但在学习时能帮助更好的了解语法或程序的工作,而且在实际使用中更能让你更快更准确的编写程序或解决程序中的问题。

C51指针的使用的更多相关文章

  1. keil C51 指针总结

    变量就是一种在程序执行过程中其值能不断变化的量.要在程序中使用变量必须先用标识符作为变量名,并指出所用的数据类型和存储模式,这样编译系统才能为变量分配相应的存储空间.定义一个变量的格式如下: [存储种 ...

  2. C51指针类型和存储区的关系详解

    一.存储类型与存储区关系 data     --->    可寻址片内ram bdata   --->    可位寻址的片内ram idata    --->    可寻址片内ram ...

  3. C51指针小结

    一. 指针变量的定义 指针变量定义与一般变量的定义类似,其形式如下: 数据类型 [存储器类型1] * [存储器类型2] 标识符: [存储器类型1] 表示被定义为基于存储器的指针.无此选项时,被定义为一 ...

  4. Keil C51 vs 标准C

    深入理解并应用C51对标准ANSIC的扩展是学习C51的关键之一.因为大多数扩展功能都是直接针对8051系列CPU硬件的.大致有以下8类: 8051存储类型及存储区域 存储模式 存储器类型声明 变量类 ...

  5. Keil C51 知识点

    第一节 Keil C51扩展关键字     深入理解并应用C51对标准ANSIC的扩展是学习C51的关键之一.因为大多数扩展功能都是直接针对8051系列CPU硬件的.大致有以下8类: 8051存储类型 ...

  6. C51学习笔记

    转自:http://blog.csdn.net/gongyuan073/article/details/7856878 单片机C51学习笔记 一,   C51内存结构深度剖析 二,   reg51.头 ...

  7. keil c51笔记

    第一章 Keil C51开发系统基本知识 第一节 系统概述 Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上.结构性.可读性. ...

  8. [转]keil使用详解

    第一节 系统概述 Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上.结构性.可读性.可维护性上有明显的优势,因而易学易用.用过 ...

  9. KeilC51使用详解 (二)

    深入理解并应用C51对标准ANSIC的扩展是学习C51的关键之一.因为大多数扩展功能都是直接针对8051系列CPU硬件的.大致有以下8类: 8051存储类型及存储区域 存储模式 存储器类型声明 变量类 ...

随机推荐

  1. Android 免费短信获取国家列表和国家代码

    StringBuffer str = new StringBuffer(); for (Map.Entry<Character, ArrayList<String[]>> en ...

  2. MFC和Qt优缺点

    在网上看到的,拿来和大家一起讨论下. 我曾经使用过来开发过软件,我想和大家分享我使用他们时所体会的不同之处. 我并非一个职业作家,这篇文章可能看起来不如专业的杂志和网站上的那么条理清晰.但是,我在这里 ...

  3. select poll epoll三者之间的比较

    一.概述 说到Linux下的IO复用,系统提供了三个系统调用,分别是select poll epoll.那么这三者之间有什么不同呢,什么时候使用三个之间的其中一个呢? 下面,我将从系统调用原型来分析其 ...

  4. 《Android开发艺术探索》读书笔记 (3) 第3章 View的事件体系

    本节和<Android群英传>中的第五章Scroll分析有关系,建议先阅读该章的总结 第3章 View的事件体系 3.1 View基本知识 (1)view的层次结构:ViewGroup也是 ...

  5. objective c的注释规范

    以前写android程序,每写一个函数或者类就添加对应的注释,后来领导让生成api文档,直接使用了eclipse的到处文档功能,强大又方便,这次换作ios开发,我想肯定也有对应的注释,于是上网查找了一 ...

  6. Android(java)学习笔记219:开发一个多界面的应用程序之两种意图

    1.两种意图: (1)显式意图: 在代码里面用intent设置要开启Activity的字节码.class文件: (2)隐式意图: Android(java)学习笔记218:开发一个多界面的应用程序之人 ...

  7. Java中如何分析一个案列---猫狗案例为例

    猫狗案例: 具体事务: 猫.狗 共性: 姓名.年龄.吃饭 分析:从具体到抽象 猫: 姓名.年龄--->成员变量 吃饭       ---> 成员方法 构造方法:无参.有参 狗: 姓名.年龄 ...

  8. 7-http1.1和2.0的区别?

    1.多路复用:减少tcp请求 合并成一个2.首部压缩:会把多个首部压缩3.服务器推送:不用request也可以response

  9. mysql查看binlog日志

    1.语法:(用于在二进制日志中显示事件.如果您不指定’log_name’,则显示第一个二进制日志.LIMIT子句和SELECT语句具有相同的语法.) show binlog events [IN 'l ...

  10. ASP.NET中 分析器错误:发现不明确的匹配

    这是一个不好的代码习惯引起的发布后运行时的问题.错误原因为.net2.0无法正确识别服务器控件和变量的大小写区别,但是这个错误只有在iis中体现,在文件系统的调试中没有发生. 错误信息 引发错误的参考 ...