C指针和引用实用.pptx
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_05.gif)
《C指针和引用实用.pptx》由会员分享,可在线阅读,更多相关《C指针和引用实用.pptx(81页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、概述概述 指针是C+语言的重要概念,利用指针可以高效而简洁的处理数据,有些操作不借用指针是无法完成的(如直接访问内存地址、动态分配内存)。因此指针成为灵活编程的重要工具。但万事有利就有弊,在程序中不加节制的滥用指针将造成程序的数据流混乱,可读性下降等问题。所以在使用指针时要多一分小心。第1页/共81页预备知识预备知识 内存就是内部存储器,由存储单元组成。它的特点是存储单元是线性连续的。存储单元的最小单位是字节。正如我们的住房都有门牌号码一样,为了访问内存中的某个存储单元,我们也要为它编号,这种编号称为内存地址。通过地址我们就能够访问该地址所标示的存储单元。0123203地址内容45第2页/共8
2、1页 在程序中定义了一个变量,这个变量在内存中就要占用一定大小的空间,通常这个空间的大小就由这个变量的类型决定。变量在内存中总是占用几个连续的字节,开始字节的地址就是变量的地址。int i;char ch;float f1;i=10;ch=A;f1=3.14;3.14A10地址变量2000200420052008ichf14字节1字节4字节第3页/共81页什么是指针什么是指针 指针就是变量的地址。与此对应,在C+语言中使用一种专门的变量-指针变量来存放另一变量的地址。也就是说,指针变量是存放地址数据的变量,它的值应该是某个变量的地址。指针变量变量地址(指针)变量变量的值指向地址存入指针变量第4
3、页/共81页 一般来说,指针变量只能存放某一种数据类型的变量地址,由此可以将指针变量划分为整型指针变量、实型指针变量、字符型指针变量等等。整型指针变量只能存放整型变量的地址。实型指针变量只能存放实型变量的地址。字符型指针变量只能存放字符型变量的地址。当把变量的地址存入指针变量后,我们就可以说这个指针指向了该变量。指针变量pi2000变量i变量i的值指向地址2000第5页/共81页指针的定义指针的定义 指针定义的结构形式如下:数据类型名 *指针变量名如:int*ptr1,*ptr2;float*ptr3;char*ptr4;在定义指针时要注意以下几个问题:1。指针变量名前面的星号“*”不能省略,
4、如果写成 int*ptr1,ptr2;则ptr2被定义为整型变量而非指针变量。2。定义中的星号“*”表示所定义的变量是指针变量,但指针变量名是ptr1、ptr2,而非*ptr1、*ptr2。第6页/共81页3。指针变量只能指向定义时所规定类型的变量。如ptr1只能指向整型变量,ptr4只能指向字符型变量。4。定义指针变量后,并未确定该变量指向何处。也就是说变量的值是不确定的。在引用指针变量前,必须首先让它确定一个变量,这一点非常重要。第7页/共81页指针的赋值指针的赋值 指针的赋值运算就是把地址值赋值给指针变量。指针的赋值运算可以是以下几种方式:1。使用取地址运算符&。如:int i,a5,*
5、ptr;ptr=&i;ptr=&a1;2。把指针变量的值赋值给另一个指针变量。如:int i,*ptr1=&i,*ptr2;ptr2=ptr1;可不可以把a赋值给ptr,即ptr=a;?可以!a即为数组的首地址。ptr=a;等价于ptr=&a0;第8页/共81页3。给指针变量赋值为赋号常量NULL,如:int*ptr;ptr=NULL;实际上NULL是一个空指针,这样的指针不指向任何变量。为了避免指针变量的非法引用,我们一般要给没有被初始化的指针变量赋值为NULL作为标志。4。把指针变量赋值为0。如:int*ptr=0;这里的0等价于NULL,值0是唯一能够直接赋值给指针变量的整数值。第9页/
6、共81页&(取地址运算取地址运算)和和*(引用运算引用运算)地址运算符&的作用是取变量的地址,如:&i表示求变量i的地址。引用运算符*的作用是取指针所指向变量的内容,例如:*ptr表示求指针ptr所指向变量的内容。&运算和*运算是一对互逆运算。20003指针ptr2000 iptr指向了i变量*ptr表示取所指向变量i的值,即3int i=3,*ptr;ptr=&i;*ptr=15;?20002000 i指针ptr*ptr=15等价于i=15,因此改变了变量i的值。15第10页/共81页例:void main()char ch=A,*ch_ptr;ch_ptr=&ch;cout“ch=”che
7、ndl;cout“*ch_ptr=”*ch_ptrendl;*ch_ptr=X;cout“ch=”chendl;cout“*ch_ptr=”*ch_ptrendl;cout“ch的地址是”ch_ptr;输出结果ch=A*ch_ptr=Ach=X*ch_ptr=Xch的地址是0 xFFF5第11页/共81页指针的指针的+、-运算运算 指针可以加上或减去一个整数,指针的这种运算的意义和通常的数值的加减运算的意义不同。指针的加减运算分为两种:一种是指针与整型值的加减运算,一种是指针与指针的减运算。struct student int number;char name4;student*pst;pst
8、=pst+1;pst第12页/共81页指针运算是地址的运算(T*px)一:px+n,px-n 将指针从当前位置向前或向后移动n个数据单位,而不是n个字节。这取决于指针所指向的数据类型(T)。pxn的结果为:px nsizeof(T)二:指针与指针的加运算毫无意义。三:指针与指针的减运算不同于简单的数值之间相减,它用来计算两指针位置之间的数据个数,而不是地址差。px-py的结果为:(px-py)/sizeof(T)注意:px和py必须具有相同指针类型!四:y=px+y=(px+),注意优先级和结合顺序(*和+优先级相同且为左结合)y=+pxy=(+px)问题:y=px+和y=(px)+的意义 第
9、13页/共81页int*ptr1,*ptr2;int a5=2,4,6,8,10;int x;ptr1=&a0;ptr2=ptr1+3;x=ptr2-ptr1;地址ptr1ptr2a数组108642200020042008200C20102000200C第14页/共81页指针的关系运算指针的关系运算一:是对两个相同类型的指针的运算,如pxpy,当px所指位置在py之前时,表达式的值为1,否则为0。二:px=py 判断两个指针是否指向同一个存储单元三:px=0,px!=0用来判断px是否为空指针四:不同类型的指针以及指针和一般整数间的关系运算是无意义的第15页/共81页指针的类型转换指针的类型转
10、换 如果两个指针类型相同,那么可以把一个指针赋给另一个指针,否则必须用强制类型转换运算把赋值运算符右边指针的类型转换为赋值运算符左边指针的类型。已知:float a=5.6;int*ptr_a;求:如何让整型指针ptr_a指向浮点型变量a ,如何通过指针ptr_a输出变量a的值?void main()float a=5.6;int*ptr_a;ptr_a=(int*)&a;cout*(float*)ptr_a;第16页/共81页main()int i=3;char*p1,temp;p1=(char*)&i;temp=*p1;*p1=*(p1+1);*(p1+1)=temp;cout*(int*
11、)p1;例:如何交换一个整型变量在内存单元里的高低字节的内容。0000001100000000高字节低字节0000000000000011高字节低字节输出结果:768第17页/共81页结构体类型的指针结构体类型的指针 也可以创建结构体类型的指针变量,其一般格式与创建基本类型的指针变量类似:存储类型 *;结构体类型的指针变量访问结构体中的成员的方法与一般的结构体变量不同,其一般格式如下:;第18页/共81页struct personchar name10;unsigned age;unsigned long id;float salary;void main()person per1,*per2
12、=&per1;strcpy(per2-name,Mary);per2-age=18;per2-id=20021001;per2-salary=2250.0;coutnametaget idtsalaryn;per1.id=20021001/(*per2).salary=2250.0第19页/共81页指针与数组的关系指针与数组的关系 声明了一个数组TYPE arrayn,则数组名称array就有了两重含义:第一,它代表整个数组,它的类型是TYPEn;第二,它是一个指针,该指针的类型是TYPE*,该指针指向的类型是TYPE,也就是数组单元的类型,该指针指向的内存区就是数组第0号单元,该指针自己占有
13、单独的内存区,注意它和数组第0号单元占据的内存区是不同的。该指针的值是不能修改的,即类似array+的表达式是错误的。因此数组与指针有着密切关系,他们几乎可以互换,数组名就是一个常量指针。所以引用指针的概念,要表示数组元素除了可以用下标表示外,还可以用指针位移表示。第20页/共81页如:int array5=1,2,3,4,5,*ptr;ptr=array;要求:输出数组array的各个元素值。下标法:一:for(i=0;i5;i+)coutarray i;二:for(i=0;i5;i+)coutptr i;位移法:一:for(i=0;i5;i+)cout*(ptr+i);二:for(i=0;
14、i5;i+)cout*(array+i);以上是一维数组元素的指针表示法,那么二维数组元素用指针如何表示呢?是否和一维数组一样?第21页/共81页如:int a34=1,2,3,4,5,6,7,8,9,10,11,12;如何用指针表示a01?最简单的方法:int*p=&a00;则*(p+1)即表示a01,很显然数组名a是一指针,那是不是*(a+1)就表示a01呢?我们知道二维数组可以看成特殊的一维数组,这个特殊的一维数组的元素又是一个一维数组。即a34可看成数组长度为3的一维数组,而此一维数组的每个元素又是一个数组长度为4的一维数组。如下图所示:aa0a1a2a00,a01,a02,a03第2
15、2页/共81页aa0a1a2a00,a01,a02,a03 因此,数组名a代表这个特殊的一维数组的首地址,它指向第一个元素a0,则a+1就指向a1,即二维数组的第二行元素,这行元素占4个存储单元。我们称a为行指针,同理a+1、a+2也是行指针。显然*(a+1)不表示a01。那么如何让指针真正指到每行上的列元素呢?即我们真正关心的二维数组的每一个元素。第23页/共81页aa0a1a2a00,a01,a02,a03 注意:a0对二维数组a来说是元素名,但对一维数组a00,a01,a02,a03来说却是数组名,此为它的双重身份。很显然a0就指向a00,因此a0+1才指向a01,我们称a0为列指针,同
16、理a1、a2也是列指针。因此*(a0+1)就表示a01。而a0用指针a可表示为*(a+0)即*a,a1表示为*(a+1)。第24页/共81页aa0a1a2a00,a01,a02,a03问题一般化:&aij=ai+j=*(a+i)+j 相对应的元素是:aij=*(ai+j)=*(*(a+i)+j)这就是二维数组元素的指针表示法。参考教材P149可以认为:在行指针前加*,可将行指针转换成列指针。第25页/共81页下面我们讨论行指针、列指针的定义方法。已知:int a34;怎样定义列指针?输出aij?很简单,只要注意把a的列指针表示方法赋给新的指针即可。如:int*p;p=&a00;或 p=a0;或
17、 p=*a;cout*(p+4*i+j);如何定义行指针呢?问题稍微复杂,新的指针必须指向行,它由4个列元素组成,也就说这个指针应指向一个一维数组,如下定义:int (*p)4;/见教材P155 p=a;或 p=&a0;cout*(*(p+i)+j);可以认为:在列指针前加&,可将列指针转换成行指针。第26页/共81页指针与字符串的关系指针与字符串的关系 字符串在内存以字符数组存放,自然与指针相关联。定义一:char s=“ABC”;定义二:char*s=“ABC”;s称之为字符指针变量,它指向字符串“ABC”,即s代表字符串“ABC”的首地址,亦即字符A所在内存单元的地址。第27页/共81页
18、 我们知道,字符串是不能直接赋值给字符数组的,要使用函数strcpy,但字符串可直接赋值给字符指针。因此:char*s=“ABC”;可等价为:char*s;s=“ABC”;注意:s为指针,它的值只能为地址,语句s=“ABC”是表示把字符串“ABC”所在内存单元的地址赋给S,因此不可认为s的值为字符串“ABC”。用指针表示的字符串输出同样可使用 cout指针变量名;上例即 couts;第28页/共81页 例 用指针实现字符串的拷贝(教材P150)void main(void)char s1=I am a student!;/定义数组并初始化 char*s2=You are a student!;
19、/定义指针并初始化 char s330,s430,s530;int i;char*p1=s3,*p2=s1;/定义指针并初始化 for(;*p1+=*p2+;);/s1拷贝给s3 for(i=0;i=strlen(s1);i+)s4i=s1i;/s1拷贝给s4 strcpy(s5,s2);/s2拷贝给s5第29页/共81页指针数组指针数组 我们先看一个指针定义 char*s4;由于 比*的优先级高(请参考P18),因此以上定义首先定义了一个数组长度为4的一维数组,而数组元素为字符指针。我们称之为指针数组。(注意区分 char(*s)4 与指针数组对照,我们称它为数组指针)第30页/共81页 我
20、们可以初始化这个字符指针数组,如:char*s4=“open”,”new”,”save”,”save as”;newsavesave asopenS0 S1 S2 S3 该指针数组元素指向不同的字符串,注意不要误认为字符串存放在该指针数组。顾名思义,指针数组只存放指针,因此该指针数组存储的实际上是各字符串的首地址。第31页/共81页 大家还注意到各字符串的长度可以不一样,这是字符指针数组的一大特点,和二维数组相比(思考如何用二维数组存放这几个字符串?),它大大节省了内存存储空间。(为什么?)二维数组表示如下:char s48=“open”,”new”,”save”,”save as”;S0S1
21、S2S30saevas0000evas00000wen0000nepo第32页/共81页例 将若干个字符串按升序排序后输出(教材P152)void main(void)char*str=;/定义数组并初始化 char*p1;/定义指针 int i,j,k;/按升序排序(改进后的选择排序)for(i=0;i=4;i+)k=i;for(j=i+1;j0)k=j;/k记为当前最小字符串的位置if(k!=i)p1=strk;strk=stri;stri=p1;/交换指针的指向,stri和strk均为指针第33页/共81页指针与函数指针与函数 指针可以用作函数参数,这在想通过调用函数来改变参数的值很重要
22、。void swap(int,int);void main()int x1=100,x2=200;cout“交换前x1=“x1“,x2=”x2endl;swap(x1,x2);cout“交换后x1=“x1“,x2=”x2;void swap(int a,int b)int temp;temp=a;a=b;b=temp;100200 x1x2x1=100,x2=200进入swap函数x1,x2分别将值赋给a,btempab100200100200100temp=a;a=b;b=temp;a,b的交换不影响x1,x2退出swap,x1、x2未交换第34页/共81页void swap(int*,in
23、t*);void main()int x1=100,x2=200;cout“交换前x1=“x1“,x2=”x2endl;swap(&x1,&x2);cout“交换后x1=“x1“,x2=”x2;void swap(int*p1,int*p2)int temp;temp=*p1;*p1=*p2;*p2=temp;100200 x1x2x1=100,x2=200进入swap函数,分别将x1、x2的地址赋给p1,p2p1p2temp&x1&x2100200100temp=*p1;*p1=*p2;*p2=temp;swap函数执行过程中p1,p2的值没有变化,退出swap函数后,x1,x2的值交换。第
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 指针 引用 实用
![提示](https://www.deliwenku.com/images/bang_tan.gif)
限制150内