3.3.3 指针
指针就是指变量或数据所在的存储器地址。例如,一个字符型的变量STR存放在内存单元data区的51 H这个地址中,那么data区的51H地址就是变量STR的指针。在C51语言中指针是一个很重要的概念,正确有效地使用指针类型的数据,能更有效地表达复杂的数据结构,能更有效地使用数组或变量,能方便直接地访问内存或其他存储器。指针之所以能有效地操作数据,是因为程序的指令、常量、变量或特殊寄存器都要存放在内存单元或相应的存储器中,这些存储器是按字节来划分的,每一个存储单元都能用唯一的编号去读或写数据,这个编号就是常说的存储单元的地址,而读写这个编号的动作就称作寻址,通过寻址能访问到存储器中任意一个能访问的单元。C51语言因此引入了指针类型的数据类型,专门用来确定其他类型数据的地址。用一个变量来存放另一个变量的地址,那么用来存放变量地址的变量称为指针变量。例如,用变量STRIP来存放STR变量的地址51 H,变量STRIP就是指针变量。图3-1说明了变量的指针和指针变量这两个不一样的概念。
图3-1 变量的指针和指针变量概念图例
变量的指针就是变量的地址,用取地址运算符“&”取值赋给指针变量。“&STR”就是把变量STR的地址取得。用语句STRIP=&STR能把所取得的STR指针存放在STRIP指针变量中,STRIP的值就变为51H。可见指针变量的内容是另一个变量的地址,地址所属的变量称为指针变量所指向的变量。
要访问变量STR除了能用“STR”这个变量名来访问之外,还能用变量地址来访问。先用“&STR”取变量地址并赋予STRIP指针变量,然后就能用*STRIP来对STR进行访问了。“*”是指针运算符,用它能取得指针变量所指向地址的值。在图3-1中指针变量STRIP所指向的地址是51 H,而51 H中的值是40 H,那么*STRIP所得的值就是40 H。使用指针变量和使用其他类型的变量一样,要求先定义变量,而且定义形式也相类似。
一般的定义形式如下:
在定义形式中数据类型是指所定义的指针变量所指向的变量的类型。存储器类型是编译器编译时的一种扩展标识,它是可选的。在没有存储器类型选项时,则定义为一般指针;有存储器类型选项时,则定义为基于存储器的指针。限于51系列单片机的寻址范围,指针变量最大的值为0x FFFF,这样就决定了一般指针在内存上会占用3字节,第一字节存放该指针存储器类型编码,后两个则存放该指针的高低位址。基于存储器的指针因为不用识别存储器类型,所以会占1或2字节;idata、data、pdata存储器指针占1字节;code、xdata占2字节。由上可知,明确的定义指针能节省存储器的开销,这在严格要求程序体积的项目中很有用处。
下面用实例说明指针的基本使用方法。
为了能清楚地了解指针的工作原理,可以使用KeilμVision软件仿真器查看各变量和存储器的值。先编译程序并执行,然后打开变量窗口,如图3-2所示。用单步执行,就能查到指针的变量。图3-2中所示的是程序中循环执行到第二次,这个时候指针dsi指向c:0x0004这个地址,这个地址的值是0x FE。在存储器窗口能查看各地址单元的值。
图3-2 指针例程仿真图