第8章指针

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

第八章指针考核知识点●指针与指针变量的概念,指针与地址运算符●变量、数组、字符串、函数的指针及指向变量、数组、字符串、函数的指针变量。通过指针引用以上各类型数据。●用指针作为函数参数●指针数组、指向指针的指针重要考点提示●对指针概念的理解●指针作为函数的参数●字符类型指针的操作●对指针的理解8.1关于地址和指针要想搞清楚地址和指针的概念,首先要清楚变量在内存中的存储方式及变量是如何被存取的。我们知道,在程序中定义的某个变量,在编译时系统会给这个变量相应地分配与该变量类型相匹配的内存单元。即按照程序中所定义的变量的类型,分配与该变量类型所占相同长度的空间。在内存中每一个字节都有一个编号,这个编号就是“地址”,它相当于每个变量的房间号。变量的数据就存放在地址所标识的内存单元中,变量中的数据其实就相当于仓库中各个房间存放的货物。如果内存中没有对字节进行编号,系统将无法对内存进行管理。内存的存储空间是连续的,因此内存中的地址号也是连续的,并且用二进制数表示,为了直观起见,这里我们用二进制进行描述。一向微机使用的C系统为整型变量分配2个字节,为实型变量分配4个字节,为字符型变量分配1个字节,为双精度类型变量分配8个字节。当某一变量被定义后,其内存中的地址也就确定了。例如:intx,y;floatz;xyz20122013201520162201220222032204图8-1x,y,z的存储单元分配这时,系统为x和y分配两个字节存储单元,为z分配了4个字节的存储单元,如图8-1所示,图中的数字只是表示字节的地址。每个变量的地址是指该变量所占存储单元的第一字节的地址。在这里,我们称x的地址为2012,y的地址为2015,z的地址为2201。在一般情况下,我们在程序中只需定义变量并指出变量名,无须去知道每个变量在内存中具体地址,由C编译系统来完成每个变量与其具体地址发生联系的操作。在程序中我们对变量进行存取操作,实际上也就是对某个变量的地址存储单元进行操作。这种直接按变量的地址存取变量的方式称为“直接存取”方式。在C语言中,还可以用另一种称为“间接存取”的方式来完成对变量进行存取的操作,即将变量的地址存放在另一种类型的变量中,从而通过这种新的变量类型来得到变量的值。按C语言规定,可以在程序中定义整型变量、实型变量、字符型变量等,也可以通过定义这样一种特殊的变量,它是专门用来存放地址的。假设我们定义了一个变量p,用来存放整型变量i的地址,它的地址被分配为1010字节,可以通过下面语句将i的地址(1500)存放到p变量中:p=&i;这时,p的值就是1500,即变量p所占用单元的起始地址。要存取变量i的值,也可以用间接的方式,先找到存放“i的地址”的变量p,从中取出i的地址(1500),然后到1500、1501字节取出i的值。由于通过地址能找到所需的变量单元,我们就可以说:地址“指向”该变量单元。所谓“指向”就是通过地址来体现。在C语言中,将地址形象地称为“指针”,意思是通过它能找到以它为地址的内存单元,这里包含有一个方向指向的意思。一个变量的地址称为变量的“指针”。一个专门用来存放另一个变量的地址的变量(即指针),则称它为“指针变量”。8.2变量的指针和指向变量的指针变量1.指针变量的定义定义指针变量的一般形式如下:类型名*指针变量名1,*指针变量名2,...;如int*p,*i;以上定义语句中,p和t都是合法用户标识符,在每个变量前的星号(*)是一个类型说明符,用来标识该变量是指针变量。提示:变量前的星号不可省略若省略了星号说明符,就变成了把p和t定义为整型变量(int是类型名)。在这里,说明了p和t是两个指向类型(int类型)变量的指针,也就是说变量p和t中只能存放int类型变量的地址,这时我们称int是指针变量p和t的基类型。基类型用来指定该指针变量可以指向的变量的类型。为什么指针变量要用“基类型”呢?一个指针变量中存放的是一个存储单元的地址值。这里“一个存储单元”中的“一”所代表的字节数是不同的:对整型而言,它代表两个字节,对实型而言,它就代表4个字节,这就是基类型不同的含义。在以后涉及到指针的移动,也就是要对地址进行增差事运算这时指针移动的最小单位是一个存储单元,而不是一个字节。因此,对于基类型不同的指针变量,其内容(地址值)增1、减1所“跨越”的字节数是不同的。故指针变量必须区分基类型,基类型不同的指针变量不能混合使用。2.指针变量的引用指针变量中只能存放地址(指针),将一个整型变量(或任何其他非地址类型的数据)赋给一个指针变量是不允许的。如:int*p;/*定义一个指向整型变量的指针*/p=300;/*300为整数*/是不合法的的赋值。与指针相关的两个运算符是“&”(取地址运算)和“*”指针运算符。3.指针变量作为函数参数前面的介绍过,函数参数可以是整型、实型、字符型等数据,指针类型数据同样也可以作为函数参数来进行传递。它的作用是将一个变量的地址传送到另一个函数中,参与该函数的运算。如果想通过函数调用从而得到n个要改变的值,可以采用如下方法:⑴在主调函数中设n个变量,分别用n个指针变量指向它们。⑵然后将各个指针变量作为实参,即将这n个变量的地址传给所调用的函数的形参。⑶通过形参指针变量的改变,从而改变这n个变量的值。⑷主调函数中就可以使用这些心改变了值的变量。形参指针变量的值的改变不能使实参指针变量的值发生改变。8.3数组与指针一个数组包含若干个元素(变量),在定义时被分配了一段连续的内存单元。因此,可以用一个指针变量来指向数组的着地址,通过该首地址就可以依次找到其他数组元素,同样指针变量也可以指向数组中的某一个元素。所谓数组的指针是指数组的起始地址,数组元素的指针是各个数组元素的地址。1.指向数组元素的指针C语言规定数组名代表数组的首地址,也就是数组中第0号元素的地址。有如下语句:intc[10]={0};int*p;p=c;则语句p=c;与语句p=&c[0];是等价的。提示:数组c不代表整个数组。上述“p=c;”的作用是把数组c的着地址赋值给指针变量p,而不是把数组c中各元素的值赋给p。定义指向数组元素的指针变量的方法与定义指向变量的指针变量相同。例如:intc[10],*p;p=&c[5];指针变量p指向了数组c中下标为5的那个元素,即p用来保存c[5]的地址。2.通过指针引用数组元素按C语言的规定:如果指针变量p已指向数组中的一个元素,则p+1指向数组中的下一个元素(而不是将p的值简单加1),这里的加1是指增加一个长度单位(与数组基类型所占存储单元相同)。例如,数组元素是浮点型,每个元素占4个字节,则p+1意味着使p的值(是一个地址)加4个字节,以使它指向下一个元素。提示:将++和运算符用于指针变量是十分有效的,可以使用指针变量自动向前或向后移动,指向下一个或上一个数组元素。不过要小心利用,否则会导致内存错误。用数组名作为函数参数数组名可以用做函数的形参和实参。当数组名作为参数被传递时,基形参数组中各元素发生了变化,则原实参数组各元素的值也随之变化。因为数组名作为实参时,在调用函数时把数组的着地址传送给形参,因此实参数组与形参数组共占一段内存单元。而如果用数组元素作为实参的情况就与用变量作为实参时一样,是“值传递”方式,单向传递,即使形参数组值发生了变化,原实参的数组元素值也不会受影响。用变量名作为函数参数和用数组名作为函数参数做比较的情况见表8-1实参类型要求形参的类型传递的信息通过函数调用参数改变实参的值变量名变量名变量的值不可以数组名数组名或指针变量数组的起始地址可以3.指向多维数组的指针和指针变量有如下定义:intc[3][4],*p;c是该二维数组的数组名,它代表了整个数组的首地址,也就是第0行的首地址,c+1代表第1行的首地址,即c+1是c[1]的地址。c[0]、c[1]、c[2]既然是一维数组名,而C语言又规定了数组名代表数组的首地址,因此c[0]代表第0行的一维数组中第0列元素的地址,即&[0][0]。同样地,c[1]的值是&[1][0]。第0行第1列元素的地址怎么表示呢?可以用c[0]+1来表示。此时“c[0]+1中的“1”代表1个列元素的字节数,即两个字节。如c[0]的值是2020,则c[0]+1的地址是2022。根据上面的介绍,c[i]t*(c+i)等价,因此,c[0]+1和*(c+0)+1的值都是&c[0][1],都是表示第0行第1列的元素的地址。c[i]从形式上看是数组c中第i个元素。如果c是二维数组名,则c[i]代表一维数组名。c[i]本身并不占实际的内在单元,它也不存放数组中各个元素的值,它只是一个地址。c、c+i、c[i]、*(c+i)+j、c[i]+j都是地址,*((c+i)+j)、*(*(c+i)+j)是元素的值。具体举例见表8-2。数组元素表举例表示形式含义地址举例c二维数组名,数组首地址,0行首地址2020c[0],*(c+0),*c第0行第0列元素地址2020c+1、&c[i]第一行首地址2028c[1]、*(c+1)第1行第0列元素地址2028c[1]+2、*(c+1)+2、&c[1][2]第1行第2列元素地址2032*(c[2]+2)、*(*(c+2)+2)、c[2][2]第2行第2列元素值该元素的值8.4字符串与指针1.字符串的表示形式⑴用字符数组存放一个字符串,然后输出该字符串。例如:charstr[]=“Iamastudent”;printf(“%s\n”,str);⑵用字符指针指向一个字符串。可以不定义数组,而定义一个字符指针,用字符指针指向字符串中的字符。例如:char*str=”Iamastudent.”;/*定义str为指针变量,并指向字符串的着地址*/printf(“%s\n”,str);在这里没有使用字符数组,而是在程序中定义了不念旧恶字符指针变量str,并使该指针变量指向一个字符串的首地址。C语言对字符串常量是按字符数组进行处理的,在内存中开辟了一个字符数组来存放字符串常量。程序在定义字符指针变量str时,把字符串的首地址赋给str。str只能指向一个字符变量或其他字符类型数据,不能同时指向多个字符数据,更不能理解为把字符串中的全部字符存放到str中(指针变量只能存放地址)。在输出时,利用字符型指针str的移动来控制输出,直到遇到字符串结束标志‘\0’为止。提示:通过字符数组名或字符指针变量可以一次性输出的只有字符数组(即字符串),而对一个数值型号的数组,是不能企图用数组名输出它的全部元素的,只能借助于循环逐个输出元素。显然,用%s可以控制对一个字符串进行整体的输入输出。对字符串中字符的存取,与操作其他数组的方法相同,即可以用下标方法,又可以用指针方法。2.字符串指针作函数参数将一个字符串从一个函数传送到另一个函数,可以用地址传递的办法,即用字符数组名作为参数或用指向字符串的指针变量作为参数,进行传递。提示:字符串指针变量作为函数实参,形参可以是字符指针变量,同样也可以是字符数组名作为参数或用指向字符串的指针作为参数,进行了传递。3.字符指针变量和字符数组的区别虽然字符数组和字符指针变量都能实现对字符的存储和运算但它们两都之间有如下区别:⑴字符数组是由若干个元素组成的,每个元素中存放一个字符,而字符指针变量中存放的是地址(字符串的着地址),绝不是将字符串的内容存放到字符指针变量中。⑵赋值方式。只能对字符数组各个元素赋值,不能用以下方法对字符数组赋值:charstr[20];str=”Iamhappy.”;⑶字符数组可以在定义时对其整体赋初值(即初始化),但在赋值语句中不能完成整体赋值。下面的做法是不允许地:charstr[30];str[]=”Iamhappy.”;而字符指针变量既可以在定义时赋初值,也可以出现在赋值语句中,相对来说要比字符数组使用起来灵活一点。⑷如果定义了一个字符数组,在编译时,系统会为它分配一段连续的内存单元,它的地址是确定的。而当定义了一个字符指针变量后,就要即时给该指针分配内存单元,该指针变量中可以存放一个地址值勤,

1 / 15
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功