(1.3)--第8章 C语言程序设计指针.ppt
《(1.3)--第8章 C语言程序设计指针.ppt》由会员分享,可在线阅读,更多相关《(1.3)--第8章 C语言程序设计指针.ppt(74页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第第8章章 指针指针8.1 引例引例8.2 指针与指针变量指针与指针变量8.3 指针与函数指针与函数8.4 指针与一维数组指针与一维数组8.5 指针与二维数组指针与二维数组8.6 指针与字符串指针与字符串8.7 二维指针与指针数组二维指针与指针数组8.8 指针程序设计示例指针程序设计示例 指针指针标示标示了内存中的一个了内存中的一个“位置位置”,其作用类似于数组的下标。,其作用类似于数组的下标。8.1 引例引例#includeint main()int i,max=0,a5=0,10,20,30,40;int*pmax,*pa;/*定义指针变量定义指针变量pmax 和和pa*/pa=pmax=
2、a;for(i=1;i5;i+)if(amaxai)max=i;printf(nmax is%d,amax);max为数组最大元为数组最大元素在数组中的位置素在数组中的位置pmax为数组最大元为数组最大元素在内存中的位置素在内存中的位置for(i=0 i5;i+)if(*pmax*pa)pmax=pa;pa+;printf(nmax is%d,*pmax);return 0;内存地址内存地址012230-1内存内存8.2 指针与指针变量指针与指针变量每个内存单元每个内存单元都是一个字节都是一个字节每个内存单元都每个内存单元都有一个编号,称有一个编号,称为为内存地址内存地址内存地址内存地址是内存
3、单元的编号,从是内存单元的编号,从0开始编号,假设计算机有开始编号,假设计算机有1G内存,则内存地址编号范围为内存,则内存地址编号范围为02 -1。注意:注意:实际输出内存地址时,是以十六进制显示的。实际输出内存地址时,是以十六进制显示的。30关于内存关于内存内存地址内存地址100101102103内存内存 第一个内第一个内存单元的地存单元的地址,称为变址,称为变量的量的地址地址或或首地址。首地址。单个变量所单个变量所被分配的内存被分配的内存单元是连续的单元是连续的一一个个变变量量8.2.1 地址和指针地址和指针 变量的值存变量的值存储在这些内存储在这些内存单元中单元中指令与内存指令与内存对于
4、以下代码,假设变量对于以下代码,假设变量a被分配的内存单元为被分配的内存单元为 20002003:int a=67;scanf(%d,&a);/*假设用户输入假设用户输入100*/printf(%d,a);直接访问和间接访问直接访问和间接访问 使用使用a或变量地址或变量地址2000访问变量的内访问变量的内存空间称为存空间称为直接访问直接访问。将变量将变量a的地址存储到变量的地址存储到变量p中,使中,使用变量用变量p访问变量访问变量a的内容,称为的内容,称为间接间接访问访问。“间接间接”的意思是使用变量的意思是使用变量p访问变量访问变量a。这时,称这时,称p指向指向a,a是是p所指向的所指向的“
5、对象对象”或或“目标目标”。指针与指针变量指针与指针变量n指针就是某个对象(变量、数组和函指针就是某个对象(变量、数组和函数等)所占用的内存单元的起始地址。数等)所占用的内存单元的起始地址。n指针的作用在于说明从一个内存地址开指针的作用在于说明从一个内存地址开始有一个指定类型的对象。始有一个指定类型的对象。n存放指针的变量称为指针变量,右图存放指针的变量称为指针变量,右图中,中,p为指针变量,指针变量中存储一为指针变量,指针变量中存储一个内存地址。个内存地址。变量变量a的指针的指针地址地址2000处有一个处有一个int型的变量型的变量指针变量指针变量p指针变量定义的形式为:指针变量定义的形式为
6、:类型名类型名*指针变量名指针变量名=地址地址;指针变量与一般变量的定义方式基本相同,例如:指针变量与一般变量的定义方式基本相同,例如:int*p;/*定义指针变量定义指针变量p,p的类型是的类型是指针指针*/8.2.2 指针变量的定义和初始化指针变量的定义和初始化其中:其中:n类型名类型名:是指针变量所指向对象的类型;:是指针变量所指向对象的类型;n *:是用于区分指针变量和其它类型变量的字符;是用于区分指针变量和其它类型变量的字符;n=地址地址:用于在定义时初始化指针变量,可省略。:用于在定义时初始化指针变量,可省略。指针变量的初始化(赋值)可以在定义指针时或者在定义指针变量的初始化(赋值
7、)可以在定义指针时或者在定义指针后进行,常见的方式有指针后进行,常见的方式有4种:种:1.1.指针指向变量的初始化指针指向变量的初始化 指针指针指向变量,使用取变量的地址运算符指向变量,使用取变量的地址运算符“&”,初始化方式为:,初始化方式为:指针变量名指针变量名=&变量名;变量名;例如:例如:定义时初始化:定义时初始化:int a=67,*pa=&a;定义后初始化:定义后初始化:int a=67,*pa;pa=&a;/*此处不能为此处不能为*pa=&a*/上述两种形式等价。在上述两种形式等价。在pa中保存变量中保存变量a的地址,称的地址,称pa指向指向a。指针变量的初始化指针变量的初始化p
8、a的类型是指针,的类型是指针,int 是是pa所指向的对象的类型。所指向的对象的类型。n 指针的类型说明与指针所指向对象的类型应当一致。指针的类型说明与指针所指向对象的类型应当一致。图中图中pa变量与变量与a变量均为变量均为int类型;类型;假设假设pa的地址为的地址为3000,a的地址为的地址为2000,则初始化后,则初始化后pa与与a的关系如图。的关系如图。指针与指针所指向变量指针与指针所指向变量npa与与a是两个不同的变量,其关系为是两个不同的变量,其关系为pa指向指向a;n使用使用pa和和a均可以访问内存地址均可以访问内存地址2000开始的内容,使用开始的内容,使用a访访问称为问称为直
9、接访问直接访问,使用,使用pa访问称为访问称为间接访问间接访问。指针指向数组初始化的方式为:指针指向数组初始化的方式为:指针变量名指针变量名=数组名;数组名;例如:例如:定义时初始化:定义时初始化:int a5,*p=a;定义后初始化:定义后初始化:int a5,*p;p=a;/*此处不能为此处不能为p=&a*/上述两种形式等价。上述两种形式等价。2.2.指针指向数组的初始化指针指向数组的初始化在在C语言中,一维数组名是数组的指针,指向数组首元素。语言中,一维数组名是数组的指针,指向数组首元素。n使用数组名初始化指针变量时,不使用使用数组名初始化指针变量时,不使用“&”运算符;运算符;n使用数
10、组中的元素初始化指针变量时,需要使用使用数组中的元素初始化指针变量时,需要使用“&”运算符。运算符。使用数组名和数组元素初始化指针:使用数组名和数组元素初始化指针:使用数组名初始化指针:使用数组名初始化指针:int a5,*p=a;使用数组元素地址初始化指针:使用数组元素地址初始化指针:int a5,*p=&a0;对于一维数组,两种方式等价。对于一维数组,两种方式等价。使用指针变量初始化其它指针变量的方式为:使用指针变量初始化其它指针变量的方式为:指针变量名指针变量名1=指针变量名指针变量名2;例如:例如:定义时初始化:定义时初始化:float a=3.5,*pa=&a;float*pb=pa
11、;定义后初始化:定义后初始化:float a=3.5,*pa,*pb;pa=&a;pb=pa;3.3.使用指针变量初始化其它同类型指针变量使用指针变量初始化其它同类型指针变量指针初始化为指针初始化为0或或NULL的方式为:的方式为:指针变量名指针变量名=0(NULL)其中:指针初始化为其中:指针初始化为0或或NULL,表示其目前,表示其目前还未指向任何对象。还未指向任何对象。例如:例如:double*pd=NULL;/*等价于等价于 pd=0*/4.4.指针可以被初始化为指针可以被初始化为0 0或或NULLNULLNULL是标准头文件是标准头文件中定义的中定义的宏常量。宏常量。【例例8.2】不
12、同类型指针变量的长度。不同类型指针变量的长度。#includevoid main()int*i;char*c;long*L;float*f;printf(n%d%d%d%d,sizeof(i),sizeof(c),sizeof(L),sizeof(f);运行结果:运行结果:4 4 4 4 指针变量中保存的是所指对象的内存地址,指针变量指针变量中保存的是所指对象的内存地址,指针变量本身的长度是一个固定值,与指针的类型无关。本身的长度是一个固定值,与指针的类型无关。指针变量的长度指针变量的长度使用指针的常见的错误:使用指针的常见的错误:使用未初始化的指针使用未初始化的指针 int*pa;print
13、f(%d,*pa);/*输出一个随机的结果输出一个随机的结果*/指针赋值常量指针赋值常量float*pf=12.345 /*编译报错编译报错*/int*pi=100/*不能将一个非地址的值存放到指针变量中不能将一个非地址的值存放到指针变量中*/void 类型指针表示类型不确定的指针类型指针表示类型不确定的指针int a=100;void*pa=&a;printf(n%d,*pa);/*错误错误*/int a=100;void*pa=&a;printf(“n%d”,*(int*)pa);/*正确正确*/指针与初始化指针的对象类型不一致指针与初始化指针的对象类型不一致double a=1.2;in
14、t*pa=(int*)&a /*(*pa)将获得意料之外的结果将获得意料之外的结果*/访问指针所指的对象的运算符有两个访问指针所指的对象的运算符有两个*和和:8.2.3 指针变量的引用指针变量的引用&运算符的作用是取变量的地址,运算符的作用是取变量的地址,*运算符用于取指针所指对运算符用于取指针所指对象的值。因而,表达式象的值。因而,表达式*(&a)与与a等价。等价。注意指针变量的双重作用。注意指针变量的双重作用。(2)下标运算符下标运算符 ,取指针所指对象的值。,取指针所指对象的值。左边的操作数左边的操作数必须是指针,并且它已指向了确定的对象。必须是指针,并且它已指向了确定的对象。例如:例如
15、:int a=5,*p;p=&a;则:则:*p和和p0均可用于获得变量均可用于获得变量a的值,即的值,即5。(1)间接访问运算符间接访问运算符*,取指针所指对象的值。取指针所指对象的值。*右边的操作右边的操作数必须是指针,而且它已指向了确定的对象。数必须是指针,而且它已指向了确定的对象。运行结果:运行结果:a=10,*pa=10b=100,*pb=100b=100,*pb=10【例例8.3】访问指针所指变量。访问指针所指变量。程序代码:程序代码:#includevoid main()long a,b;long*pa,*pb;pa=&a,pb=&b;*pa=10;*pb=100;指针变量前没有指
16、针变量前没有“*”运运算符,表示访问指针变算符,表示访问指针变量量pa和和pb本身。本身。printf(na=%ld,*pa=%ld,a,*pa);printf(nb=%ld,*pb=%ld,b,*pb);pb=pa;printf(nb=%ld,*pb=%ld,b,*pb);运行结果:运行结果:12,23 max is 23,min is 12,sum is 35【例例8.4】输出两个数的关系与和。输出两个数的关系与和。#includevoid main()int a,b,*pa=&a,*pb=&b,*pc=NULL;scanf(%d,%d,pa,pb);等价于等价于scanf(%d,%d,&
17、a,&b)if(pa0pb0)pc=pa;pa=pb;pb=pc;pa0 可用可用*pa等价替换,等价替换,pb0 可用可用*pb等价替换等价替换printf(nmax is%d,min is%d,sum is%d,pa0,pb0,pa0+pb0);8.3 指针与函数指针与函数 8.3.1 指针作为函数的参数指针作为函数的参数 指针作为函数的形参时,在形参说明时需要使用指针作为函数的形参时,在形参说明时需要使用格式格式 类型名类型名*指针名指针名 其中,其中,“*”号不可省略。号不可省略。函数定义时:函数定义时:void changeA(int*p)/*说明需要一个地址作为参数说明需要一个地址
18、作为参数*/*p=*p+*p;声明函数定义时:声明函数定义时:void changeA(int*p)/*表示需要一个地址作为参数表示需要一个地址作为参数*/或或void changeA(int*)/*p可以被省略,但可以被省略,但*不能省略不能省略*/【例例8.5】指针作为形参的函数调用。指针作为形参的函数调用。void changeA(int*);void main()int a=10,*pa=&a;printf(“n调用前调用前:pa=%x,a=%d,pa,a);changeA(pa);printf(“n调用后调用后:pa=%x,a=%d,pa,a);void changeA(int*p)
19、int b;*p=*p+*p;p=&b;printf(“n调用中调用中:p=%x,p);运行结果:运行结果:调用前:调用前:pa=18ff44,a=10调用中:调用中:p=18ffe4调用后:调用后:pa=18ff44,a=20【例例】若有函数定义为若有函数定义为“int f(int x,int*y)return x/*y;”,下面声明该函数的正确形式是下面声明该函数的正确形式是 。Avoid f(int,int);Bint*f(int,int*);Cint f(int*,int*);Dint f(int,int*);分析:分析:A选项错误,函数类型声明错误,形参选项错误,函数类型声明错误,形
20、参y为整型指针,声明时为整型指针,声明时*号不可省略;号不可省略;B选项错误,函数类型声明错误,函数名前有多余的选项错误,函数类型声明错误,函数名前有多余的“*”;C选项错误,第一个形参声明错误,因其并不是指针参数;选项错误,第一个形参声明错误,因其并不是指针参数;D选项正确,函数声明与函数定义一致。选项正确,函数声明与函数定义一致。指针作为参数时,必须保证数据类型一致指针作为参数时,必须保证数据类型一致【例例8.6】使用函数实现交换两个变量的值。使用函数实现交换两个变量的值。#includevoid swap(int*p1,int*p2)int t;t=*p1;*p1=*p2;*p2=t;p
21、rintf(在函数中:在函数中:*p1=%d,*p2=%dn,*p1,*p2);int main()int a=10,b=20;int*pa=&a,*pb=&b;printf(调用函数之前:调用函数之前:a=%d,b=%dn,a,b);swap(pa,pb);printf(调用函数之后:调用函数之后:a=%d,b=%dn,a,b);return 0;运行结果:运行结果:调用函数之前:调用函数之前:a=10,b=20在函数中:在函数中:*p1=20,*p2=10调用函数之后:调用函数之后:a=20,b=10两个返两个返回值回值 使用指针作为函数的参数,其实质是让函数访问其作用范围使用指针作为函数
22、的参数,其实质是让函数访问其作用范围之外的变量,从而获得之外的变量,从而获得“返回值返回值”的效果。的效果。void swap(int p1,int p2)int c;c=p1;p1=p2;p2=c;printf(nin swap:p1=%d,p2=%d,p1,p2);错误原因:错误原因:p1和和p2不是指针类型的变量不是指针类型的变量错误形式错误形式1swap()函数的函数的3种错误方式种错误方式1 错误原因:错误原因:p1与与p2是指针变量,而是指针变量,而c是是简单变量。简单变量。错误形式错误形式2void swap(int*p1,int*p2)int c;c=p1;p1=p2;p2=c
23、;printf(nin swap:p1=%d,p2=%d,p1,p2);swap()函数的函数的3种错误方式种错误方式2 错误原因:指针与指针所指向的对象是相互错误原因:指针与指针所指向的对象是相互独立的两个独立的两个“变量变量”,操作,操作p1和和p2并不能影并不能影响到响到p1和和p2所指向的对象。所指向的对象。错误形式错误形式3void swap(int*p1,int*p2)int*c;c=p1;p1=p2;p2=c;printf(nin swap:p1=%d,p2=%d,p1,p2);swap()函数的函数的3种错误方式种错误方式3 返回值是指针类型的函数称为返回指针值的函数。返回值是
24、指针类型的函数称为返回指针值的函数。返回指针值的函数的一般形式为:返回指针值的函数的一般形式为:数据类型名数据类型名 *函数名函数名(参数表参数表)8.3.2 返回指针值的函数返回指针值的函数例如:例如:int *max(int n);其中:其中:max是函数名,是函数名,n是函数是函数max()的形参,的形参,函数名前面的函数名前面的“*”表示调用该函数后可返回一个指表示调用该函数后可返回一个指向整型数据的指针。向整型数据的指针。必须确保函数执行后,指针所指对象处于其生必须确保函数执行后,指针所指对象处于其生存期内,否则有可能会导致程序异常。存期内,否则有可能会导致程序异常。#include
25、int main()int*p;int*max(int n);p=max(8);printf(max is%dn,*p);return 0;int*max(int n)/*定义指针函数定义指针函数*/static int a=13,24,38,27,11,9,36,18;int i,m=0;for(i=1;in;i+)if(amai)m=i;return&am;运行结果:运行结果:max is 38函数中的数组的存储类型函数中的数组的存储类型要求为静态(要求为静态(static),否),否则,函数返回时,数组已则,函数返回时,数组已经被释放,则返回地址无经被释放,则返回地址无效。效。【例例8.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 1.3-第8章 C语言程序设计指针 1.3 语言程序设计 指针
限制150内