《指针的概念指针变量的定义和引用指针与一维数组指针与字符串指针与二维数组二级指针.pptx》由会员分享,可在线阅读,更多相关《指针的概念指针变量的定义和引用指针与一维数组指针与字符串指针与二维数组二级指针.pptx(61页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、19.0 指针导入 为什么要学习指针?指针是指针是C C语言的重要特色。语言的重要特色。使用指针可以使用指针可以:使程序简洁、紧凑、高效使程序简洁、紧凑、高效 得到多于一个的函数返回值得到多于一个的函数返回值 有效地表示复杂的数据结构有效地表示复杂的数据结构 动态分配内存动态分配内存 能方便地使用字符串、数组能方便地使用字符串、数组 能直接处理内存地址能直接处理内存地址 等等第1页/共61页2已知斜塔地址已知斜塔地址9.1 指针的概念指针二者是同一个概念的两种说法。只不过指针更形象一些,就像一个针一样,可以指向某个地方。指针:就是地址。第2页/共61页39.1 指针的概念指针:一个变量的地址指
2、针变量:专门存放变量地址的变量(存放的数据内容是地址)变量i的地址.2000200420062005整型变量i10变量i_pointer2001200220032000指针指针变量变量i的内容指针变量i_pointer中存放的是i的首地址2000指针变量指向目标变量第3页/共61页49.1 指针的概念变量的访问直接访问和间接访问 有两个上锁并且放着物品的盒子A、B,如何要把A里的东西拿出来?情况1:如果你有A盒子的钥匙,则可以直接打开A盒子将物品取出;情况2:如果你有B盒子的钥匙,而A盒子的钥匙在B盒子中,要想取出A盒子中的物品,则必须先打开B盒子,取出A盒子的钥匙,再打开A盒子将物品取出。上
3、面两种情况就是直接访问和间接访问的概念。第4页/共61页5源程序中通过变量名存取变量。编译后程序中将不存在变量名。运行时通过地址存取变量。9.1 指针的概念直接访问:按变量地址存取变量值间接访问:通过存放变量地址的变量去访问变量例 i=3;-直接访问指针变量.2000200420062005整型变量i3变量i_pointer2001200220032000例 通过指针变量i_pointer访问-间接访问此时,称该指针变量i_pointer指向变量i第5页/共61页69.1 指针的概念指针变量.2000200420062005整型变量i10变量i_pointer2001200220032000整
4、型变量k例 k=i;-直接访问 k=*i_pointer;-间接访问10第6页/共61页7 数据在内存中的地址是由编译器在编译阶段决定的;编程时,变量地址的具体值不可知,只能通过取地址符或数组名得到变量或数组的地址;一般情况下,编程人员不必关心数据在内存中的具体地址是多少。9.1 指针的概念说明第7页/共61页89.2 指针变量的定义和引用定义指针变量一般形式:类型名 *指针变量名表示该指针变量所指向的变量的数据类型例:int *p1,*p2;char c,*ch;float f1,f2,*p;注意:1.指针变量名是p1,p2,不是*p1,*p2。2.指针变量只能指向定义时所规定类型的变量.3
5、.指针变量定义后,变量值不确定,应用前必须先赋值。第8页/共61页9例1 先定义变量,再赋值 int a=3,*p;p不定不定a3p=&a;&a例2 定义变量的同时,赋值 int a=3,*p=&a;注意注意注意注意只能用同类型变量的地址进行赋值只能用同类型变量的地址进行赋值:如有以下定义 int *p;float a;以下赋值非法 p=&a;9.2 指针变量的定义和引用指针变量赋值第9页/共61页10不定在分析有关指针的程序时,画图是很好的方法:若有:若有:int a,*s;则则sa若有:若有:int a=5,*s=&a;则则不定5&a a9.2 指针变量的定义和引用指针变量赋值第10页/共
6、61页11两者含义不同两者含义不同两者含义不同两者含义不同定义指针变量p1*是指针运算符9.2 指针变量的定义和引用指针变量的引用例:int a,*p1,*p2;p1=&a;p2=p1;*p1=3;printf(%d,*p2);第11页/共61页12试比较设有定义 int a,*p;p=&a;p=&a;*p=&a;*p=&a;p 指针变量*pp所指向的变量,即a的内容9.2 指针变量的定义和引用有关指针的运算符:&,*&:取地址运算符。&a表示取变量a的地址。*:指针运算符(取内容运算符)。*p表示取p所指向的变量的内容。&,*:互为逆运算第12页/共61页139.2 指针变量的定义和引用指针
7、变量可进行的操作(1)赋值:int a,*p1=&a,*p2;p2=p1;(2)取内容:*p1=5;a=5;printf(“%d”,*p1);(3)增减:p1+;p1+=4;常用于数组元素的引用。(4)比较:常用于数组各个元素地址的大小比较。第13页/共61页14例例例例 改变指针变量的指向改变指针变量的指向改变指针变量的指向改变指针变量的指向#include#include void main()void main()int a1=11,a2=22;int a1=11,a2=22;int *p1,*p2;int *p1,*p2;p1=&a1;p1=&a1;p2=&a2;p2=&a2;prin
8、tf(“%d,%dn”,*p1,*p2);printf(“%d,%dn”,*p1,*p2);p2=p1p2=p1;printf(“%d,%dn”,*p1,*p2);printf(“%d,%dn”,*p1,*p2);printf(%d,%dn,a1,a2);printf(%d,%dn,a1,a2);p1&a11122a1p2a2&a2*p1*p2&a1*p1*p2第14页/共61页15 例例 两个指针变量交换指向两个指针变量交换指向#include#include void main()void main()int a1=11,a2=22;int a1=11,a2=22;int *p1,*p2,
9、*p;int *p1,*p2,*p;p1=&a1;p1=&a1;p2=&a2;p2=&a2;printf(“%d,%dn”,*p1,*p2);printf(“%d,%dn”,*p1,*p2);p=p1;p1=p2;p2=p;p=p1;p1=p2;p2=p;printf(“%d,%dn”,*p1,*p2);printf(“%d,%dn”,*p1,*p2);p1&a11122a1p2a2&a2&a2换名字不把钱拿出来,换钱包两个指针变量交换指向&a1第15页/共61页16例例 交换两个指针变量所指向的变量的值交换两个指针变量所指向的变量的值#include#include void main()v
10、oid main()int a1=11,a2=22,t;int a1=11,a2=22,t;int *p1,*p2;int *p1,*p2;p1=&a1;p1=&a1;p2=&a2;p2=&a2;printf(“%d,%dn”,a1,a2);printf(“%d,%dn”,a1,a2);t=*p1;*p1=*p2;*p2=t;t=*p1;*p1=*p2;*p2=t;printf(“%d,%dn”,a1,a2);printf(“%d,%dn”,a1,a2);p1&a11122a1p2a2&a2相当于t=a1;a1=a2;a2=t;换内容把钱放到另一个钱包里交换两个指针变量所指向的变量的值第16页
11、/共61页17int*p,m=5,n;以下正确的是 a)p=&nb)p=&n;scanf(“%d”,&p)scanf(“%d”,*p);c)scanf(“%d”,&n);d)p=&n;*p =n;*p=m;int*p1,*p2,m=5,n;正确的是:a)p1=&m;p2=&p1;b)p1=&m;p1=&n;*p1=*p2;c)p1=&m;p2=p1;d)p1=&m;*p2=*p1;第17页/共61页18函数的参数可以是各种类型的数据参数的传递是“值传递”,单向的,且只能返回一个函数值。若想在被调函数中改变主调函数中局部变量的值或从一个函数中返回多个值,将如何操作?法法1 1-全局变量全局变量(
12、但是破坏了模块的独立性)(但是破坏了模块的独立性)法法2 2-指针作为函数的参数指针作为函数的参数(地址传递)(地址传递)9.2 指针变量的定义和引用指针作为函数参数地址传递第18页/共61页19函数交换两个数的值一般变量作为函数参数 举例main()int a=1,b=2;swap(a,b);printf(“%d,%d”,a,b);swap(int x,int y)int t;t=x;x=y;y=t;1,2 分析 值传递单向传递,因而形参的值的改变并不影响实参的值。9.2 指针变量的定义和引用指针作为函数参数地址传递第19页/共61页20&a&b12aabbabswap(int*x,int*
13、y)int t;t=*x;*x=*y;*y=t;int a=1,b=2,*aa,*bb;aa=&a;bb=&b;printf(“%d,%d”,a,b);swap(aa,bb);main()分析地址传递函数中通过形参引用传来的地址,从而改变了主调函数中局部变量的值。2,12,1&ax&by*x*y21函数交换两个数的值指针作为函数的参数指针作为函数的参数 举例9.2 指针变量的定义和引用指针作为函数参数地址传递第20页/共61页21 在语言中,指针与数组有着密切的关系。对数组元素,既可以采用数组下标来引用,也可以通过指向数组元素的指针来引用。采用指针方法处理数组,可以产生代码长度小、运行速度快的
14、程序。9.3 指针与一维数组第21页/共61页229.3 指针与一维数组通过指针访问一维数组数组名就是数组的首地址,等价于第一个元素的地址,即数组名是指向数组的第一个元素的指针常量,也即数组名是表示数组首地址的地址常量。数组名是个地址常量,其值由系统编译时确定,在运行期间不能改变。第22页/共61页23aia1a0数组float a6&a0、*aa+i&ai、*(a+i)C C语言里,下标运算和指针运算是等价的a9.3 指针与一维数组通过指针访问一维数组第23页/共61页24aia1a0数组ap*pp+i&pi*(p+i)若有如下赋值语句p=a;pi9.3 指针与一维数组通过指针访问一维数组第
15、24页/共61页25指向数组元素的指针(地址)对数组元素的访问&a0&a1&aipp+1p+i&p0&p1&piaa+1a+i*a*(a+1)*(a+i)p0p1pi*p*(p+1)*(p+i)数组aa0a1ai9.3 指针与一维数组通过指针访问一维数组总 之第i个元素第i个元素的地址第25页/共61页26数组名a和指针变量p有何区别?a指针常量p指针变量p=p+2;a=a+2;p+;a+;9.3 指针与一维数组通过指针访问一维数组第26页/共61页27设有如下定义 int a5=1,3,5,7,9,i,*p;for(i=0;i5;i+)printf(“%d”,ai );*(a+i)p=a;p
16、i*(p+i)for(;p=0&ai 0);printf(“%dn”,t);下面结果是char a=“12345”,*p;int s=0;for(p=a;*p!=0;p+)s=10*s+*p 0;printf(“%dn”,s);1 12345第33页/共61页34例:编写在数组的最后一个元素中存放其它元素和的函数#include void summary(int*p,int n);void main()int a11=1,2,3,4,5,6,7,8,9,10;summary(a,10);printf(Sum is%dn,a10);void summary(int*p,int n)int s=0
17、;for(;n0;n-,p+)s+=*p;*p=s;函数还可写为:void summary(int arr,int n)int i,s=0;for(i=0;in;i+)s+=arri;arrn=s;9.3 指针与一维数组数组名作函数参数第34页/共61页35 字符串是一种特殊的一维数组,所以上节中介绍的方法同样适用于对字符串的访问。字符串的特殊性在于:字符串的末尾是结束标志 0,所以访问字符串时常用结束标志进行判断。9.4 指针与字符串第35页/共61页369.4 指针与字符串通过字符访问字符串例 main()char string=“I love China!”;printf(“%sn”,s
18、tring);printf(“%sn”,string+7);IloveChistring0string1string2string3string4string5string6string7string8string9stringstring10string11string12string13n!a0第36页/共61页37例#include stdio.h main()char *string=“I love China!”;printf(“%sn”,string);string+=7;while(*string)putchar(string0);string+;9.4 指针与字符串通过字符指针
19、访问字符串字符指针初始化:把字符串首地址赋给string char *string;string=“I love China!”;*string!=0IloveChistringn!a0string第37页/共61页38定义及初始化定义及初始化char s=“hello”;char *p=“hello”;赋值赋值char s6;char *p;s=“hello”;/*此不对此不对*/p=“hello”;strcpy(s,“hello”);strcpy(p,“hello”);使用使用s不能自加不能自加/减减 p可以自加可以自加/减减注意:注意:char s=“abc”;与与char s=a,b,
20、c;的区别的区别9.4 指针与字符串通过字符数组和字符指针使用字符串的比较第38页/共61页39下面判断真确的是a)char*a=“china”;等价于 char*a;*a=“china”;b)char str10=“china”;等价于char str10;str=“china”;c)char*s=“china”;等价于char*s;s=“china”;d)char c4=“abc”,d4=“abc”;等价于char c4=d4=“abc”;下面程序运行结果是char*s=“abcde”;s+=2;printf(“%s”,s);下面结果是:char str=“ABC”,*p=str;prin
21、tf(“%dn”,*(p+3);c cde 0第39页/共61页40下面结果是:char*p=“abcdefgh”;p+=3;printf(“%dn”,strlen(strcpy(p,”ABCD”);下面程序结果是char a=“language“,*p;p=a;while(*p!=u)printf(“%c”,*p 32);p-;若已定义 char s10;则在下面表达式中不表示s1的地址的a)s+1 b)s+c)&s0+1 d)&s14 LANG b第40页/共61页41main()char*s1=“AbDeG”;char*s2=“AbdEg”;s1+=2 ;s2+=2;printf(“%d
22、n”,strcmp(s1,s2);a)正数 b)负数 c)0 d)不能确定第41页/共61页42fun(char*s)char a7;s=a;strcpy(a,“look”);main()char*p;fun(p);puts(p);第42页/共61页43main()char*p,s=“ABCDEFG”;for(p=s;*p!=0;)printf(“%sn”,p);p+;if(*p!=0)p+;esle break;ABCDEFGCDEFGEFGG第43页/共61页44main()char*p1,*p2,str50=“abc”;p1=“abc”;p2=“abc”;strcpy(str+1,str
23、cat(p1,p2);printf(“%sn”,str);aabcabc第44页/共61页45 当一维数组的每个元素为一维数组时,便构成了二维数组。9.5 指针与二维数组 熟记下面两组等价式:xi *(x+i)&xi x+i第45页/共61页46a2a1a0aa+1a+2数组aa00a01a02a03int a34 34矩阵a10a11a12a13a20a21a22a23二维数组的结构9.5 指针与二维数组第46页/共61页47void main()int a22=1,2,3,4;printf(%dn,a);printf(%dn,*a);printf(%dn,a0);printf(%dn,a0
24、+1);printf(%dn,a0+2);printf(%dn,a+1);printf(%dn,*(a+1);printf(%dn,a1+1);printf(%dn,*a);printf(%dn,*(a+1);printf(%dn,*(a1+0);第47页/共61页48int a23;对数组a的i行j列元素值的正确引用是a)*(*(a+i)+j)b)(a+i)jc)*(a+i+j)d)*(a+i)+jint a23,对数组a的i行j列元素地址的正确引用是a)*(ai+j)b)(a+i)c)*(a+j)d)ai+jint*q5 等价的语句是a)int q5 b)int*qc)int*(q5)d)
25、int(*q)5第48页/共61页49若有以下定义,则*(p+5)表示 int a10,*p=a;a)元素a5的地址 b)元素a5的值c)元素a6的地址 d)元素a6的值 若有定义:int *p4;则标识符pa)是一个指向整型变量的指针b)是一个指针数组名c)是一个指针,它指向一个含有4个整型元素的一维数组d)说明不合法B b 第49页/共61页50若有定义:int 46;则能正确表示a数组中任意元素地址的是a)&a00+6*i+j b)&a00+4*j+ic)&a00+4*i+j d)&a00+6*j+i第50页/共61页51若有说明 char*language=“fortran”,”bas
26、ic”,”pascal”,”java”,”c”下面不正确的是a)language+2表示字符串“pascal”首地址b)*language2的值是字母pc)language是一个字符型指针数组,它包括5个元素,买个元素都是一个指向字符串变量的指针d)language是一个字符型指针数组,它包括5个元素,其初值分别是”fortran“,”basic“,“pascal”,“java”,“c”d第51页/共61页52若有下面说明和语句:char language=“fotran”,”basic”,”pascal”,”java”,”c”;char*q;q=language+2;则语句printf(“%
27、on”,*q):a)输出的是language2元素的地址b)输出的是字符串pascalc)输出的是language2元素的值,它是字符串pascal的首 地址d)格式说明不正确c第52页/共61页53a表示数组在内存中的首地址表示数组在内存中的首地址,也就是数组中第,也就是数组中第1个元素(也是第一行)的首地址,它是一个地址个元素(也是第一行)的首地址,它是一个地址常量,其值由系统在编译时确定,程序运行期间常量,其值由系统在编译时确定,程序运行期间不能改变。不能改变。该二维数组可以理解为:它是个一维数组,含有3个元素,每个元素又是一个一维数组,该一维数组含有4个元素,每个元素是int类型。首地
28、址 a a+0&a0说 明9.5 指针与二维数组第53页/共61页54思考:ai+j 是何含义?a03a02a01a00a13a12a11a10a23a22a21a20a0a1a2a+0a+1a+2a0+0 a0+1 a0+2 a0+3a1+0 a1+1 a1+2 a1+3a2+0 a2+1 a2+2 a2+3a+i 表示指向二维数组第i行的指针ai+j表示指向第i行第j列元素的指针9.5 指针与二维数组第54页/共61页55xi *(x+i)和&xi x+i 访问数组元素aij*(ai+j)*(*(a+i)+j)元素的地址&aijai+j*(a+i)+j表示法9.5 指针与二维数组第55页/
29、共61页56200020082010a+iai+0或&ai0同指向的地址都是2000异两者的数据类型不同对应变量定义为 int (*p)4;(见后)a+i和&ai0的异同点9.5 指针与二维数组第56页/共61页57(1)格式:类型名)格式:类型名 (*指针变量名)指针变量名)长度长度;(2)例如:)例如:int (*p)4,a34;(3)含义:)含义:p是指针变量,它指向含有是指针变量,它指向含有4个元素的一个元素的一维数组,每个元素的类型是维数组,每个元素的类型是int。一维数组指针变。一维数组指针变量量维数维数和二维数组和二维数组列数列数必须相同。必须相同。int (*p)4;p=a;p
30、=a+1;p+;ppp指向二维数组中一行的指针变量9.5 指针与二维数组第57页/共61页58a00a01a02a03a10a11a12a13a20a21a22a23ap (*p)0 (*p)1 (*p)2 (*p)3如果执行如果执行p+,则变为如图所示则变为如图所示pp第一行各元素还可以表示为:如上第一行各元素还可以表示为:如上那么那么(*p)i表示当前行的第表示当前行的第i个元素个元素通过(*p)i 可以访问当前行第i个的元素9.5 指针与二维数组第58页/共61页59通过(*p)i 可以访问当前行第i个的元素 举例9.5 指针与二维数组main()static int a34=1,3,5
31、,7,9,11,13,15,17,19,21,23;int i,j,(*p)4;for(p=a,i=0;i3;i+,p+)for(j=0;j4;j+)printf(%d,(*p)j);printf(n);p=a0;p=*a;p=&a00;p=&a0;p=a0;p=*a;p=&a00;p=&a0;第59页/共61页609.6 指向指针的指针一级指针:指针变量中存放目标变量的地址例 int *p;int i=3;p=&i;*p=5;&i3P(指针变量)i(整型变量)一级指针单级间接寻址二级指针:指针变量中存放一级指针变量的地址p1&p2&i3P2(指针变量)i(整型变量)例 int *p1;int *p2;int i=3;p2=&i;p1=&p2;*p1=5;二级指针一级指针目标变量二级间接寻址第60页/共61页61感谢您的观看!第61页/共61页