Click to edit Master title style,Click to edit Master text styles,Second level,Third level,Fourth level,1-,*,21,天学,51,单片机开发,第七讲:,C51,的指针,课程安排,地址和指针概述,指针变量的声明,指针变量的赋值,指针变量的运算符,特殊的指针类型,数组指针,特殊的指针类型,字符指针,地址和指针概述,内存单元是单片机存储器中的最小存储单位,通常一个字节称为一个内存单元。,单片机内存单元的编号也就是,地址,。,指针是一种特殊的数据类型,用指针声明的变量称为指针变量。,指针变量的值实际上是一个地址,是单片机内存单元的编号。,单片机中不同的数据类型所占用的内存单元数和它的大小有关。,指针变量的声明,声明一个指针变量具有特殊的形式,如下所示:,类型标识符*指针名,;,类型标识符*指针名,1,*,指针名,2,;,在声明指针变量时,应注意如下几点:,在定义指针变量时,指针名前的“*”不能省略。,同一个指针变量只能指向同一类型的变量。,指针变量的赋值,指针变量的赋值就是给予一个合理的地址值。,指针变量被声明后可以指向任何同类型的变量。,C51,中使用地址运算符“,&”,获取变量的首地址。,如果定义指针变量时不进行赋值,该指针变量被初始化为,NULL,。,指针变量的赋值,在,C51,语言中提供了灵活的指针变量赋值方法,主要有如下几种:,在声明时赋值,动态赋值,指针变量之间传递,特殊的指针变量赋值,数组,特殊的指针变量赋值,字符串,特殊的指针变量赋值,函数入口,在声明时赋值,在声明时赋值的方法比较简单,而且不占用程序执行时间。,需要使用取地址运算符,&,来完成。,典型的在声明时赋值语句,示例如下。,int a;,int*p=/,初始化赋值,,&a,表示取变量,a,的首地址,动态赋值,指针变量也可以在程序执行时动态改变指针的值。,需要使用取地址运算符,&,来完成。,典型的动态赋值语句,示例如下。,int a;,int*p;,p=/,利用,&a,获得变量,a,的首地址,然后赋值给,p,指针变量之间传递,C51,中可以将一个指针变量传递给另一个指针变量。,在指针变量之间进行地址传递时,指针变量的类型应该一致。,int a=15,b=26;/,定义变量和初始化,int*p1=/,定义指针变量和初始化,p2=p1;/,把,a,的地址赋予指针变量,p2,*p2=*p1;/,把,p1,指向的内容赋给,p2,所指的区域,特殊的指针变量赋值,数组,引用数组时应该逐个元素引用,而不能直接引用数组名。,数组名代表的是数组存放的首地址。,可以通过引用数组名而将数组首地址赋值给指针变量。,int a7,*p;/,声明数组以及指针变量,p=a;/,数组名表示数组的首地址,故可赋予指向数组的指针变量,p=/,数组第一个元素的地址也是整个数组的首地址,特殊的指针变量赋值,字符串,C51,语言中没有字符串变量,只有字符串常量。,可以把字符串的首地址赋予指向字符类型的指针变量。,char*p;/,声明字符型指针变量,p=Hello everyone!;/,赋值,char*p=Hello everyone!;,特殊的指针变量赋值,函数入口,指针变量还可以指向函数。,对指向函数的指针变量赋值,就是把函数的入口首地址赋予指向函数的指针变量。,用函数为指针变量赋值注意事项,注意其表示方法两对括号都不能省略。,对指针变量,pf,赋值时,函数名,fun,前没有地址运算符“,&”,。,在,C51,语言中,指针变量若不带初始化项,其将被初始化为,NULL,。,空指针常用于调用一个带有返回指针的函数时。,指针变量的运算符,C51,语言中提供了专门的运算符来用于指针的操作:,取地址运算符,&,取值运算符*,这些运算符可以完成取地址、赋值、取值等操作。,指针变量之间也可以进行一些关系和算术运算。,取地址运算符,&,取地址运算符,&,就是用于提取变量的地址。,取地址运算符,&,是单目运算符,符合自右至左的结合性。,取地址运算符,&,的使用格式如下:,&,变量名,取值运算符*,取值运算符*就是提取指针变量所指向内存单元中的数据内容。,取值运算符*也是单目运算符,同样符合自右至左的结合性。,取值运算符*的使用格式如下:,*,指针变量名,取值运算符*,取内容运算符*和指针变量声明中指针说明符*是不同的,读者应该分清两者的区别。,在指针变量说明中,“,*”是类型说明符,表示其后是指针类型的变量。,表达式中出现的“*”则是一个取值运算符,用来表示指针变量所指向的地址中的数据值。,指针变量的运算,指针变量是特殊的一种变量,其同样也可以参与一些运算,但是有很大的局限性。,指针变量可以参与的运算有如下几类:,关系运算,算术运算,指针变量的关系运算,指针变量参与关系运算,可以比较其所指向地址位置的高低。,例如对于两个指针变量,p,和,q,,可参与的运算如下:,若,p=q,为真,则表示,p1,和,p2,指向同一地址;,若,pq,为真,则表示,p,处于高地址位置,,q,处于低地址位置。,若,p=q,为真,则表示,p,的地址位置大于等于,q,的地址位置。,指针变量的算术运算,指针变量参与算术运算,可用实现地址的增减操作。,在,C51,语言中,指针变量和整数可进行简单的加、减运算。,具体可以使用的运算如下:,p+n,p-n,p+,+p,p-,-p,特殊的指针类型,数组指针,对数组来说,数组名就是数组在内存存放的首地址。,指针变量可以指向数组的首地址,指针变量也可以指向数组元素的地址。,这里,我们重点讨论如下几种情况:,指向一维数组的指针,指向二维数组的指针,指向一个由,n,个元素所组成的数组指针,指针和数组的关系总结,数组指针和指针数组,指向一维数组的指针,指向一维数组的指针是将指针变量指向一维数组的首地址或者某个元素的地址。,数组元素在内存中是连续存放的,通过指针变量,pp,及其有关运算可以间接访问数组中的任何一个元素。例如:,a+i,和,pp+i,均表示数组元素,ai,的地址;,*,(pp+i),和*,(a+i),都表示,pp+i,和,a+i,所指向元素的值;,指向二维数组的指针,将一个指针指向二维数组,需要首先定义一个二维数组,示例如下:,char a34=a,b,c,d,e,f,g,h,i,j,k,l;,在,C51,语言中,这个二维数组,a,可以看成是由三个一维数组元素组成。,其中每个一维数组元素又是一个包含有,4,个元素一维数组。,指向二维数组的指针,二维数组的指针指向示意,如下图所示。,对于二维数组,a,来说,,a0,、,a1,、,a2,可以看成是独立的一维数组名,其分别代表了所对应的数组的首地址。,一般来说,ai+j,代表第,i,行第,j,列元素的地址,即,&aij,。,指向一个由,n,个元素所组成的数组指针,在,C51,语言二维数组可用看成几个一位数组的组合,这几个一维数组为二维数组的各个行。,但是如果需要对列元素进行操作该如何呢?,在,C51,语言中,引入了一个指向由,n,个元素构成的数组指针。,这样可以方便二维数组列元素的处理,其定义格式如下:,类型标识符,(*,指针名,)n;,指针和数组的关系总结,指针和数组有着十分紧密的关系。,数组和指针的使用方法十分灵活,也很容易混淆,读者应该多加练习。,一般来说,任何能由数组和数组下标完成的操作,也都完全可以用指针和指针的偏移量来实现。,详细内容参阅书中介绍。,数组指针和指针数组,指针数组是同一数据类型的多个指针变量构成的一个数组。,在,C51,语言中,指针数组的定义格式如下:,类型标识符*数组名,整型常量表达式,;,指针数组的运算规则,假设指针数组名为,pch,,其满足和一般的数组一样运算规则:,pch,指针数组元素的首地址;,pch+i,为指针数组的第,i,个元素的地址;,*,pch,等价于,pch0,,为该指针数组的第一个元素;,*,(pch+i),等价于,pchi,,为数组的第,i,个元素。,对于指针数组来说,其最大的优点体现在对多个字符串的处理上。,特殊的指针类型,字符指针,字符串在,C51,语言中一直是有着特殊的地位。,字符指针,其实就是指向字符类型的指针变量。,采用字符指针可以对字符串常量进行操作,即用字符指针指向字符串,然后通过字符指针来访问字符串的存储区域。,这里需要注意的是,由于字符常量的值不可以改变,因此,通过字符指针可以访问字符串常量中的内容,但不可以对其进行修改。,特殊的指针类型,字符指针,声明一个字符指针的方法比较简单,和前面声明其他类型指针类似,示例如下:,char*pstr;,如果让该字符指针指向一个字符串,则可以采用如下的语句:,pstr=Good morning!;,