1第9章指针2第9章指针9.1为何引入指针9.2如何定义及引用指针9.3指针相关的运算9.4数组相关的指针9.5指针类型数组9.6指针与字符串9.7函数与指针9.8指针的指针9.9指针应用实例9.10小结39.1为何引入指针9.1.1以直接方式访问内存9.1.2以间接方式访问内存49.1.1以直接方式访问内存每一个变量都有两个属性:变量地址和变量值。变量的地址指示了该变量在内存中的存储位置。而变量值就是该内存中的存储内容。要访问该空间上的内容可以直接使用变量名。inta=100;printf(a的值是%d\n,a);printf(存储a的内存地址是%ld\n,&a);59.1.2以间接方式访问内存将变量a的地址存放在另一个变量b中,变量b的内存空间如下图所示。0089为变量b对应的内存地址,0090为变量b的值,同时也是变量a对应的内存地址。可以借助变量b,以*b的方式可以获得a的内容。变量b变量a1000090内存内容0088…00890090内存地址69.2如何定义及引用指针9.2.1什么是指针9.2.2如何定义指针变量9.2.3指针相关的运算符9.2.4指针的引用79.2.1什么是指针指针变量是一个特殊的变量,它存储的数值代表内存里的一个地址,用来指向另外一个变量。不同于普通变量,指针变量需要搞清楚4个概念:(1)指针变量的地址,即为指针变量分配的内存空间的地址,在上例中为0089。(2)指针变量的值,即该内存空间的内容,在上例中为0090。(3)以指针变量的值为地址的空间地址,也称为指针指向的空间地址,上例中为0090。(4)指针指向的内存空间的内容,上例中为100。89.2.2如何定义指针变量指针变量定义一般由两部分组成:基类型和指针操作符。定义指针变量的标准形式如下所示。基类型*指针变量名;例如:char*a;99.2.3指针相关的运算符指针的运算实质是地址的运算。C语言提供了两个关于指针的运算符和一套适用于指针、数组等地址运算的规则,正是这套规则赋予了C语言出色的处理能力。(1)取地址运算(&)对指针变量进行取地址运算,可以得到指针变量本身的地址。例如,对于int*p有:inta,p=&a;(2)取内容运算(*)取内容运算“*”,用于获取地址数据对应存储单元的内容。例如,对于int*p有:printf(“%d”,*p);109.2.4指针的引用指针变量的值代表内存的一个地址,指向所需要的变量。通过引用指针可以访问其所指向的内容。可以改变所指向的内容,同时也可以通过修改指针变量的值使其指向不同的内存地址。【例9-1】本实例介绍通过指针变量访问整型变量的方法。【例9-2】本实例介绍通过指针变量改变指针所指的内容。【例9-3】本实例介绍通过修改指针变量的值使其指向不同变量的方法。119.3指针相关的运算9.3.1指针相关的赋值运算9.3.2指针相关的算术运算9.3.3指针相关的关系运算129.3.1指针相关的赋值运算对指针进行赋值运算,所赋的值一定是一个地址。上节已经介绍了将一个变量的地址赋值给指向相同类型的指针,本小节介绍其他的赋值运算方法。(1)将一个指针变量的值赋给与其相同类型的指针变量【例9-4】本实例实现使两个指针指向同一个变量。(2)将数组的首地址赋值给指向和该数组相同类型的指针变量139.3.2指针相关的算术运算由于指针变量中保存的是地址,所以指针的算术运算只能是和整数作加减运算,即指针移位。(1)指针的加1或减1(自增或自减)运算【例9-5】本实例演示指针值加1和指针加1的运算。(2)指针加上或减去一个整数【例9-6】本实例介绍通过使指针加上一个整数输入输出数组元素。149.3.3指针相关的关系运算在有意义的情况下,指针是可以进行关系运算的。一般情况下,进行指针的关系运算时,两个指针都指向同一个数组中的元素,即指针的关系运算反映了指针所指向的数组中元素位置之间的关系。【例9-7】本实例演示判断两个指针是否指向同一个变量。159.4数组相关的指针9.4.1数组元素的指针9.4.2以指针方式引用数组元素9.4.3数组指针作为函数参数9.4.4指向多维数组的指针变量169.4.1数组元素的指针指向数组元素的指针变量的定义和指向变量的指针变量的定义相同。引用数组元素可以用数组下标法,也可以用指针法。1.先定义后赋值int*pt,a[10];pt=&a[0];//将a数组的第1个元素的地址取出赋给指针pt,即pt指向了数组a2.定义并初始化inta[10];int*pt=&a[0];//初始化指针pt为a数组的第1个元素的地址,即pt指向了数组a179.4.2以指针方式引用数组元素由下面的定义可知指针p指向了数组a。int*p,a[7];p=&a[0];那么,数组元素的地址和数组元素的值就有以下的表示方式:189.4.3数组指针作为函数参数当数组在调用函数和被调用函数之间传递时,如果要将数组中的每个元素都传递给被调用函数,用前面所学的方法,就是数组有多少个元素,就要在被调用函数中定义多少个参数。如果数组中的元素的个数多的话,那么这样作不但需要定义很多的形参,而且使用不便、效率低。所以,在数组要作为函数的参数进行传递时,有两种可行的基本方法——使用指向数组的指针或数组名来传递参数。【例9-12】本实例演示了利用指向数组的指针作为函数的参数实现求10个数的平均值。【例9-13】本实例演示了如何利用函数调用在数组中找出最大值。199.4.4指向多维数组的指针变量对于二维数组a[m][n]来说,是由m行和n列即m*n个元素组成。下面的代码段定义了一个二维数组a,此数组的存储情况如图所示。inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}【例9-14】本实例演示了二维数组中各个地址和元素值的输出情况。209.5指针类型数组9.5.1什么是指针数组9.5.2指针数组使用实例219.5.1什么是指针数组指针数组是由相同类型的指针变量构成的集合,是一个数组。即指针数组中每一个元素是指针变量,并且指针变量的类型相同。229.5.2指针数组使用实例【例9-16】本实例演示了如何使用指针数组实现数组元素的输入输出。【例9-17】本实例演示根据输入的星期数值代号,输出当天的课程。239.6指针与字符串9.6.1指向字符的指针9.6.2函数的字符串指针类型参数9.6.3字符串指针和字符数组的异同249.6.1指向字符的指针在C语言中,几乎所有的字符(串)操作都是通过指针来实现。指向字符类型的指针称为字符指针。259.6.3函数的字符串指针类型参数字符串需要在函数间传递时,可以用地址的方法传递,也可以用字符指针的方法传递。这样,在被调用函数中对字符串操作或改变字符串的内容,等同于在主调函数中操作。字符串作为参数传递时的形式有4种:(1)实参和形参都是字符数组名(2)实参是字符数组名,形参是字符指针(3)实参和形参都是字符指针(4)实参是字符指针,形参是字符数组名269.6.4字符串指针和字符数组的异同字符数组和字符指针都可以实现字符串的存储和操作,但是二者之间是有区别的。(1)下面的两种定义方式都是合法的。charstring1[]=IamaChinese;char*string2=IamaChinese;上面两条语句都实现了字符串的存储。但是,他们是有差别的。(2)赋值方式有区别。对字符数组只能对每个元素赋值。(3)定义一个数组时,系统会为数组分配内存单元,数组的地址就已经确定,即使字符数组未初始化,相应的存储空间也已经被预留出来。而定义一个字符指针变量,系统会为指针变量分配一个内存单元,里面可以存放一个地址。(4)数组名虽然代表了数组的首地址,但它是常量,它的值是不可以改变的,也不能和整数作加减运算。(5)如果一个指针变量指向了一个字符串,可以用下标形式引用指针变量所指的字符串中的字符。279.7函数与指针9.7.1函数指针9.7.2函数指针作函数的参数289.7.1函数指针可以定义一个指针变量指向一个函数,那么通过这个指针变量可以调用此函数,这个指针变量称为指向函数的指针变量。定义一个指向函数的指针变量的一般形式为:类型标识符(*指针变量名)();函数名代表一个函数的入口地址,所以指向函数的指针的赋值可以采用如下形式:指针变量名=函数名;调用函数既可以通过函数名调用,也可以通过函数指针调用。通过函数指针调用函数采用如下的形式:(*指针变量名)(实参列表);299.7.2函数指针作函数的参数函数的参数可以是变量、常量、数组、指向变量的指针、指向数组的指针,也可以是指向函数的指针。如果想在调用函数时想把一个函数传递给被调用函数,只需把要传递的函数名作为实参即可。309.8指针的指针9.8.1如何定义指针的指针9.8.2如何使用指针的指针319.8.1如何定义指针的指针指向指针的指针变量,简称指向指针的指针。使用指向指针的指针在建立复杂的数据结构时,能够实现其他语言难以实现的一些功能。指向指针的指针也必须先定义才能够引用。定义一个指向指针的指针的一般形式如下:类型标识符**指针变量名329.8.2如何使用指针的指针如果要引用变量n的值,可以用*p1,也可以用**p2。这时的“*”是取内容运算符,结合性是由右向左结合。*p2的结果是指针p1,**p2就是*p1,*p1的结果是变量n的值(内容)。339.9指针应用实例【例9-31】本实例演示了计算数组中所有下标为奇数的元素的和。【例9-32】一个班有若干个同学,本实例演示根据输入的人名,查找这个人是否为该班同学。【例9-33】选班长问题。选班长的原则是:将班里的所有n个同学围成一圈,顺序编号。从第一个人开始报数(从1到3报数),凡是报到3的同学退出圈子。然后从下一个人重新开始报数,直到剩下最后一个人就是班长。请输出班长开始时的编号。349.10小结指针是一个特殊的变量,它存储所知对象的内存地址。指针所指的对象可以是简单变量,也可以是数组、函数、结构、联合等。指针变量可以有空值,即该指针变量不指向任何变量。在C语言中,用“p=NULL;”表示。NULL是一个符号常量,实际上是整数0,它使指针p的存储单元中所有二进制位均为0,也就是p指向地址为0的单元。系统保证使该单元不做他用,有效数据的指针不指向0单元。虽然NULL实际上是0,但是人们一般不习惯写成“p=0;”而写成“p=NULL;”,这样可读性好。指针可以进行算术运算、关系运算和赋值运算。进行算术运算就是指针加上或减去一个整数n,就是指针向下或向上移动n个数据单位。进行关系运算时,两个指针一般都指向同一个数组中的元素,即指针的关系运算反映了指针所指向的数组中元素之间的位置关系。字符指针可以用字符串初始化,即将字符串的首地址赋给指针。