《2 C语言上机-8指针-精品文档整理.pptx》由会员分享,可在线阅读,更多相关《2 C语言上机-8指针-精品文档整理.pptx(33页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、 指指针第八章8.1 指针变量 指针是语言中一个重要的组成部分,通过指针可以实现动态的存储空间的访问,进而编写出高质量的程序。8.1.1 地址和指针n内存是以字节为单位的存储空内存是以字节为单位的存储空间,每个字节都有一个编号,间,每个字节都有一个编号,而这个编号称为而这个编号称为内存地址内存地址。n定义的变量都是存放在内存中定义的变量都是存放在内存中的,当使用的时候,则通过内的,当使用的时候,则通过内存的编号找到所定义的空间位存的编号找到所定义的空间位置,进而对数据进行存取。即置,进而对数据进行存取。即通过通过地址地址对变量进行访问的。对变量进行访问的。n例如:例如:int a=10;200
2、02004100a图8-1 变量的存储形式8.1.1 地址和指针n指针则是存放地址的一种变量,指针则是存放地址的一种变量,指针的值是存储单元的地址,指针的值是存储单元的地址,而而不是一个一般的数值,通过这个不是一个一般的数值,通过这个地址同样对变量进行访问。地址同样对变量进行访问。n图图8-1中的变量中的变量a,可以使用指针,可以使用指针存放存放2000这个内存地址,通过对这个内存地址,通过对指针的访问,间接的访问指针里指针的访问,间接的访问指针里面的地址所指向的数据面的地址所指向的数据100。20002004100a图8-1 变量的存储形式8.1.2 指针变量的定义、赋值和引用指针变量的定义
3、1指指针变量里针变量里面存放的是面存放的是地地址。址。指指针变量的类型要和针变量的类型要和它指它指向的变向的变量的类量的类型一致型一致。指指针变量定义的一般形式针变量定义的一般形式:类类型关键字型关键字 *指针变量名指针变量名;例如,例如,int*p1;/定义一个指向整型数据的指针变量定义一个指向整型数据的指针变量p1double*p2;/定义一个指向双精度实型数据的指针变量定义一个指向双精度实型数据的指针变量p2char*p3;/定义一个指向字符型数据的指针变量定义一个指向字符型数据的指针变量p3注意:指针变量名前面的星号是一个说明符,表明定义的变量是指针变量。其中,注意:指针变量名前面的星
4、号是一个说明符,表明定义的变量是指针变量。其中,p1、p2和和p3都是指针变量,分别用于存放整型、实型和字符型变量的存储空间的都是指针变量,分别用于存放整型、实型和字符型变量的存储空间的地址,指针变量在内存中存放,本身也有地址编号。地址,指针变量在内存中存放,本身也有地址编号。8.1.2 指针变量的定义、赋值和引用n指针变量里面存放的是一个地址,所以可以利用指针变量里面存放的是一个地址,所以可以利用取地址运算符取地址运算符(&)将一个变量的地址赋予指针变量,将一个变量的地址赋予指针变量,例如例如:int m=10;int*p;p=&m;注意:注意:1.在指针变量的赋值时,一定要保证指针的类型要
5、与所指变量的类在指针变量的赋值时,一定要保证指针的类型要与所指变量的类型一致;型一致;2.不能将一个整数不能将一个整数直接直接赋给指针变量赋给指针变量;指针变量的赋值28.1.2 指针变量的定义、赋值和引用n指针指针变量变量可以可以被被赋值赋值,但必须有具体的指向但必须有具体的指向。例如例如:float m=1.23;float*p,*q;p=&m;/m的地址的地址 q=p;/复制另一个指针复制另一个指针 p=&m;/指指针针p有有了具体指向,即存放了变量了具体指向,即存放了变量m的地的地址址q=p;/将将p的指向赋给指针变量的指向赋给指针变量q,指针变量,指针变量q里面也存放了里面也存放了m
6、的地的地址。址。指针变量的赋值28.1.2 指针变量的定义、赋值和引用n指针指向一个指针指向一个“空空”值值例如例如:int*p;p=NULL;NULL是一个空值,对应的是一个空值,对应的ASCII码为码为0,所以也可以写成,所以也可以写成p=0,但它的意义是但它的意义是使指针变量使指针变量不不指向指向任何空间任何空间,而不是指向一个而不是指向一个地址为地址为0的存储空间。的存储空间。指针变量的赋值28.1.2 指针变量的定义、赋值和引用n在使用指针的时候,首先要熟练掌握两个运算符:在使用指针的时候,首先要熟练掌握两个运算符:(1)&取地址运算符。取地址运算符。(2.1)*针对指针变量的定义而
7、言,叫做指针变量标识;针对指针变量的定义而言,叫做指针变量标识;(2.2)*针对针对指针变量的引用,间接访问运算符指针变量的引用,间接访问运算符(取内容运算符取内容运算符)例如例如:int a=10;int*p;p=&a;/p指向了指向了a的地址的地址 printf(%dn,*p);int*p;语句中的语句中的“*”代表指针变量的标识代表指针变量的标识;输出语句中的输出语句中的“*”代表取代表取 指针变量指针变量p的值(某地址)的值(某地址)里面的里面的内容内容,p的的值值是是a的地址的地址(p=&a),*p 实际上就是取实际上就是取&a里里面的数据,即面的数据,即10。指针变量的引用38.1
8、.2 指针变量的定义、赋值和引用例例8-1 使用指针实现两个实型数据的输入和输出。使用指针实现两个实型数据的输入和输出。#includemain()float m,n;float*p1,*p2;p1=&m;p2=&n;scanf(%f%f,p1,p2);/等价于等价于scanf(%f%f,&m,&n);printf(m=%f n=%fn,*p1,*p2);8.1.2 指针变量的定义、赋值和引用 1u如果一个指针本身没有具体的指向,则不能给其它指针变量赋值,如果一个指针本身没有具体的指向,则不能给其它指针变量赋值,也不能取里面的内容。也不能取里面的内容。例如例如:int*p,*q,m;q=p;/
9、错误,指针错误,指针p没有具体指向没有具体指向 m=*p;/错误,指针错误,指针p没有具体指向没有具体指向注意:注意:8.1.2 指针变量的定义、赋值和引用 2u如如指针指针已已有具体指向有具体指向,间接运算符(,间接运算符(*)也可以用在赋值符号)也可以用在赋值符号的左边的左边例如例如:int a=10,b=20;int*p,*q;p=&a;q=&b;*q=*p;/等价于等价于b=a;语句,语句,b中的数值变为中的数值变为10同理:同理:*q=*p+10;/等价于等价于b=a+10;如:如:int i=1,j=2,*p=&j,*q;q=p;scanf(“%d%d”,&i,q);printf(
10、“%d,%d,%d,%d”,i,j,*p,*q);若输入若输入 10 20 ,则输出为:则输出为:如:如:int i=1,j=2,k,*p=&i ;k=*p+j;printf(“%d,%d,%d”,*p,j,k);则输出为:则输出为:阅读程序段,写出输出结果:阅读程序段,写出输出结果:10,20,20,20 1,2,3 分析与理解:分析与理解:假设有假设有 int a,*p=&a;分析下分析下面的表达式的面的表达式的正正误误:*&a&*a *&p&*p8.2 指针和数组8.2.1 指针和一维数组u数组在内存中是一个连续的存储空间,常常可以借助于指针对数组在内存中是一个连续的存储空间,常常可以借
11、助于指针对其进行访问。例如,有如下代码,其进行访问。例如,有如下代码,uint a5=10,20,30,40,50;u如图如图8-1所示,对于一维数组而言,数组的名字所示,对于一维数组而言,数组的名字a是一个地址常是一个地址常量,即第一个存储单位的地址,即量,即第一个存储单位的地址,即a与与&a0完全等价。完全等价。8.2 指针和数组8.2.1 指针和一维数组u可以可以使使用指用指针存取数组:针存取数组:定义指定义指针针p,令,令p指向了指向了数组的起始地址数组的起始地址,p的增的增减就是地址的前后偏移,减就是地址的前后偏移,即可指向当前数组元素即可指向当前数组元素的前后元素。的前后元素。+p
12、;/指针增加一个单位,指向指针增加一个单位,指向a1printf(%d,*p);/输出输出a1中的数据中的数据20printf(%d,*(p+2);/本位置之后的两个地址偏移量的值,即本位置之后的两个地址偏移量的值,即a3printf(%d,*(+p);/输出输出p指针指向的位置指针指向的位置a2的值的值30 178.2.1 指针和一维数组(1)下标法一维数组的输入和输出,则有三种表达形式:一维数组的输入和输出,则有三种表达形式:#includemain()int a5;int i;for(i=0;i=4;i+)scanf(%d,&ai);for(i=0;i=4;i+)printf(%4d,a
13、i);l对于数组来说,下标法是一种基础的引用形式,如果程序代码比较简单,对于数组来说,下标法是一种基础的引用形式,如果程序代码比较简单,建议使用此方法建议使用此方法。188.2.1 指针和一维数组(2)地址偏移量法#includemain()int a5;int i;for(i=0;i=4;i+)scanf(%d,a+i);/地址偏移量地址偏移量 for(i=0;i=4;i+)printf(%4d,*(a+i);/间接取内容运算间接取内容运算l地址偏移量是利用数组的名字地址偏移量是利用数组的名字a,加上一个偏移量(存储单位)对数组中的地址逐一引用,加上一个偏移量(存储单位)对数组中的地址逐一引
14、用,当输出时,则将地址的前面加上间接取内容运算符,对数组中的数据进行引用。同理,当输出时,则将地址的前面加上间接取内容运算符,对数组中的数据进行引用。同理,可以定义一个指针变量可以定义一个指针变量p指向起始地址,将输入和输出的地址常量指向起始地址,将输入和输出的地址常量a换成指针变量换成指针变量p,实,实现的效果是相同的现的效果是相同的。l不三不不三不四,不常用。四,不常用。198.2.1 指针和一维数组(3)指针移动法#includemain()int a5;int*p;for(p=a;p=a+4;p+)scanf(%d,p);/指针指向地址指针指向地址 for(p=a;p=a+4;p+)p
15、rintf(%4d,*p);/指针移动,间接取内容运算指针移动,间接取内容运算l在地址常量偏移法中,虽然可以应用指针,但指针没有移动,始终指向了数组在地址常量偏移法中,虽然可以应用指针,但指针没有移动,始终指向了数组的起始地址,而对于指针移动法而言,指针首先指向数组的起始地址,之后每的起始地址,而对于指针移动法而言,指针首先指向数组的起始地址,之后每次接收或者输出一个数值都是移动了指针,改变了实际指向次接收或者输出一个数值都是移动了指针,改变了实际指向。l也不常用,但考试常用。也不常用,但考试常用。使用指针操作数组的基使用指针操作数组的基本语本语句句,常考,需常考,需要记住要记住for(p=数
16、组名数组名;p数组名数组名+数组长度数组长度;p+).;.*p.;.;8.2.1 指针和一维数组例例8-2 编写程序,使用指针逐一输出一个字符串中的各个字符。编写程序,使用指针逐一输出一个字符串中的各个字符。程序分析:下标法的判断依据是程序分析:下标法的判断依据是stri!=0,而针对指针,而针对指针,可以可以直接判断直接判断*p(等价于(等价于*p!=0)。)。#include#includemain()char str20;char*p;p=str;gets(str);while(*p)printf(%c,*p);p+;/指针向后移动一个位置指针向后移动一个位置 其中,其中,while条件
17、中的条件中的*p的意义是的意义是p指针所指向的存储空间的数据,如指针所指向的存储空间的数据,如果遇到果遇到0,其值为,其值为0,则条件为假,退出循环。,则条件为假,退出循环。指针指针补充:补充:补充:补充:8.3 8.3 字符串和指针字符串和指针字符串和指针字符串和指针u1.字符串的表示形式字符串的表示形式u2.字符指针与字符数组的异同字符指针与字符数组的异同指针指针8.3.1 8.3.1 字符串的表示形式字符串的表示形式字符串的表示形式字符串的表示形式方法一:用字符数组存放一个字符串方法一:用字符数组存放一个字符串 如:如:char s =“I Love China!”;ILoveChina
18、!0s0s1s2s3s4s5s6s7s8s9s10s11s12s13s方法二:用字符指针指向一个字符串方法二:用字符指针指向一个字符串如:如:char *s=“I Love China!”;ILoveChina!0s指针指针8.3.1 8.3.1 字符串的表示形式字符串的表示形式字符串的表示形式字符串的表示形式例例8.3.1-1:将字符串:将字符串a复制为字符串复制为字符串b(用字符数组来处理)(用字符数组来处理)#include stdio.hmain()char a =Program Design,b20;int i;for(i=0;ai!=0;i+)bi=ai;bi=0;printf(n
19、String a is:%s,a);printf(nString b is:);for(i=0;bi!=0;i+)printf(%c,bi);指针指针8.3.1 8.3.1 字符串的表示形式字符串的表示形式字符串的表示形式字符串的表示形式例例8.3.1-2:将字符串:将字符串a复制为字符串复制为字符串b(用字符指针来处理)(用字符指针来处理)#include stdio.hmain()char a =Program Design,b20,*p1,*p2;int i;for(p1=a,p2=b;*p1!=0;p1+,p2+)*p2=*p1;*p2=0;printf(nString a is:%s
20、,a);printf(nString b is:);for(i=0;*(b+i)!=0;i+)printf(%c,bi);指针指针8.3.2 8.3.2 字符指针与字符数组的异同字符指针与字符数组的异同字符指针与字符数组的异同字符指针与字符数组的异同字符数组和字符指针都能实现字符串的存储和运算字符数组和字符指针都能实现字符串的存储和运算字符数组和字符指针之间的区别:字符数组和字符指针之间的区别:1.字符数组由若干元素组成,每个元素可保存一个字符字符数组由若干元素组成,每个元素可保存一个字符变量变量;而字符指针存放的是字符串而字符指针存放的是字符串常量常量的起始地址的起始地址2.1)数数组名是常
21、量组名是常量,字字符数组只能初始化符数组只能初始化,不,不能被整体赋值能被整体赋值 如:如:char str20=“Program Design”;不可写成:不可写成:char str20;str=Program Design;但其局部可改:但其局部可改:str0=F;2)字字符指针是变量符指针是变量,可以被赋值,可以被赋值,如如:char*str=Program Design;等价于:等价于:char*str;str=Program Design;之后还可改变之后还可改变:str=“ABC”;/指向另一个字指向另一个字符串符串常量常量 但但字符指字符指针针指指向的是向的是字符串字符串常常量量
22、,该串不可改:,该串不可改:str0=F;是是错错的。的。8.2.2指针和二维数组/自学,期末基本不考n对于二维数组中元素的引用,可以通过下标法,对于二维数组中元素的引用,可以通过下标法,但同样也可以通过指针的形式加以引用。如图但同样也可以通过指针的形式加以引用。如图8-3所示,有如下定义,所示,有如下定义,nint a34=1,2,3,4,5,6,7,8,9,10,11,12;n每个元素中上面的数值代表数据存储的地址编每个元素中上面的数值代表数据存储的地址编号,下面的是实际存储的内容,号,下面的是实际存储的内容,a0,a1,a2是各个行的起始地址,如果想表示元素是各个行的起始地址,如果想表示
23、元素7的的地址,常用的下标引用为地址,常用的下标引用为&a12,另外一种,另外一种形式则用地址偏移量的方法表示,即形式则用地址偏移量的方法表示,即a1+2。由此,可以得到表由此,可以得到表8-1和表和表8-2,8.2.2指针和二维数组表8-1 二维数组地址的引用下标引用下标引用地址引用地址引用地址编号地址编号&a00,&a01,&a02,&a03&a00,&a01,&a02,&a03a0+0,a0+1,a0+2,a0+3a0+0,a0+1,a0+2,a0+32000,2004,2008,20122000,2004,2008,2012&a10,&a11,&a12,&a13&a10,&a11,&a
24、12,&a13a1+0,a1+1,a1+2,a1+3a1+0,a1+1,a1+2,a1+32016,2020,2024,20282016,2020,2024,2028&a20,&a21,&a22,&a23&a20,&a21,&a22,&a23a2+0,a2+1,a2+2,a2+3a2+0,a2+1,a2+2,a2+32032,2036,2040,20442032,2036,2040,2044表8-2 二维数组元素的引用下标引用下标引用地址引用地址引用数值数值a00,a01,a02,a03a00,a01,a02,a03*(a0+0),*(a0+1),*(a0+2),*(a0+3)*(a0+0),
25、*(a0+1),*(a0+2),*(a0+3)1,2,3,41,2,3,4a10,a11,a12,a13a10,a11,a12,a13*(a1+0),*(a1+1),*(a1+2),*(a1+3)*(a1+0),*(a1+1),*(a1+2),*(a1+3)5,6,7,85,6,7,8a20,a21,a22,a23a20,a21,a22,a23*(a2+0),*(a2+1),*(a2+2),*(a2+3)*(a2+0),*(a2+1),*(a2+2),*(a2+3)9,10,11,129,10,11,128.2.2指针和二维数组二维数组中的任意一个位置二维数组中的任意一个位置aij,可以使用如
26、下形式加以引用:,可以使用如下形式加以引用:(1)aij地址的引用地址的引用&aij,ai+j,*(a+i)+j(2)aij元素的引用元素的引用aij,*(ai+j),*(*(a+i)+j)关于二维数组地址和元素的引用,可以追溯到一维数组的基础之上,关于二维数组地址和元素的引用,可以追溯到一维数组的基础之上,一维数组一维数组ai如果用地址引用的形式可以写成如果用地址引用的形式可以写成*(a+i),所以这里结合,所以这里结合了指针和一维数组的表示形式,将元素了指针和一维数组的表示形式,将元素aij的地址写成的地址写成*(a+i)+j的的形式,同理,对元素的引用整体上再加上间接取内容运算符形式,同
27、理,对元素的引用整体上再加上间接取内容运算符*(*(a+i)+j)。8.2.3指针数组和字符串/自学,期末基本不考指针数组是指向同一种数据类型地址的结合,指针数组定义的格式指针数组是指向同一种数据类型地址的结合,指针数组定义的格式:类型关键字类型关键字*指针数组名指针数组名整型常量表达式整型常量表达式;例如例如:int*p3;n定义了一个含有定义了一个含有3个存储空间的指针数组,其中指针数组中的个存储空间的指针数组,其中指针数组中的p0、p1和和p2都存放的是地址,而且只能是整型数据的地址。都存放的是地址,而且只能是整型数据的地址。8.2.3指针数组和字符串如果有变量的定义语句,如果有变量的定
28、义语句,int a=3;int b=4;可以通过指针数组中的各元素对其进行指向和引用,例如,可以通过指针数组中的各元素对其进行指向和引用,例如,p0=&a;/p0指向变量指向变量ap1=&b;/p1指向变量指向变量bp2=p0;/p2也指向变量也指向变量a8.2.3指针数组和字符串n如果使用指针数组对变量的值进行引用,则前面加上间接取内容如果使用指针数组对变量的值进行引用,则前面加上间接取内容运算符(运算符(*)如:如:*p0和和*p1则分别代表变量则分别代表变量a和和b。对于一个字符串的输入和输出,使用指针变量实现起来比较容易,对于一个字符串的输入和输出,使用指针变量实现起来比较容易,但是,
29、当一次性处理多个字符串时,情况就比较复杂,如果使用指但是,当一次性处理多个字符串时,情况就比较复杂,如果使用指针数组加以解决,则程序结构显得相对简单、灵活。针数组加以解决,则程序结构显得相对简单、灵活。8.2.3指针数组和字符串例例8-3 编写程序,使用指针数组实现三个字符串中的输入和输出编写程序,使用指针数组实现三个字符串中的输入和输出程序分析:假设输入的字符串为程序分析:假设输入的字符串为Computer、Math和和English,其在内存中,其在内存中存放的位置如图存放的位置如图8-4所示,此时定义一个指针数组,让指针数组中的各个元素指向所示,此时定义一个指针数组,让指针数组中的各个元素指向各个行的起始位置,则可以实现字符串的输入和输出。各个行的起始位置,则可以实现字符串的输入和输出。8.2.3指针数组和字符串例例8-3 编写程序,使用指针数组实现三个字符串中的输入和输出编写程序,使用指针数组实现三个字符串中的输入和输出#include#includemain()char str310;char*p3;int i;for(i=0;i=2;i+)pi=stri;/使指针中的各个元素指向各行字符串的首地址使指针中的各个元素指向各行字符串的首地址 gets(pi);/接收字符串接收字符串 for(i=0;i=2;i+)puts(pi);/输出字符串输出字符串