《C语言程序设计第九章善于利用指针.ppt》由会员分享,可在线阅读,更多相关《C语言程序设计第九章善于利用指针.ppt(66页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、 C程序设计程序设计主讲人:袁丽主讲人:袁丽燕大里仁基础教学部第九章:善于利用指针第九章:善于利用指针1 指针的概念和指针变量指针的概念和指针变量2 数组指针和指向数组的指针变量数组指针和指向数组的指针变量3 字符串指针和指向字符串的指针变量字符串指针和指向字符串的指针变量4 指针数组和指向指针的指针指针数组和指向指针的指针5 指针小结指针小结 地址指针的基本概念地址指针的基本概念一、指针变量一、指针变量 如何定义指针变量如何定义指针变量 如何引用指针变量如何引用指针变量 指针变量作为函数参数指针变量作为函数参数引:指针是什么引:指针是什么u如果在程序中定义了一个变量,在对程序进行编译时,系如
2、果在程序中定义了一个变量,在对程序进行编译时,系统就会给统就会给该该变量分配内存单元变量分配内存单元u编译系统根据程序中定义的变量类型,分配一定长度的空编译系统根据程序中定义的变量类型,分配一定长度的空间间u例如,例如,VC+VC+为整型变量分配为整型变量分配4 4个字节,对单精度浮点型变个字节,对单精度浮点型变量分配个字节,对字符型变量分配个字节量分配个字节,对字符型变量分配个字节n务必弄清楚存储单元的务必弄清楚存储单元的地址地址和存储单元的和存储单元的内容内容这两个概这两个概念的区别念的区别例如:例如:u内存区的每一个字节有一个编号,这就是内存区的每一个字节有一个编号,这就是“地址地址”,
3、它相当,它相当于旅馆中的房间号。于旅馆中的房间号。u在地址所标在地址所标识识的内存单元中存放数据,这相当于旅馆房间中的内存单元中存放数据,这相当于旅馆房间中居住的旅客一样。居住的旅客一样。u由于通过地址能找到所需的变量单元,我们可以说,地址指由于通过地址能找到所需的变量单元,我们可以说,地址指向该变量单元。向该变量单元。将地址形象化地称为将地址形象化地称为“指针指针”int i=3,j=6,k;int i=3,j=6,k;printf(“%d”,i);printf(“%d”,i);通过变量名通过变量名i找到找到i的地址的地址2000,从而从存,从而从存储单元读取储单元读取3int i=3,j=
4、6,k;int i=3,j=6,k;k=i+j;k=i+j;从这里取从这里取3将将9送到这里送到这里从这里取从这里取6直接存取直接存取int i=3,j=6,k;int i=3,j=6,k;定义特殊变量定义特殊变量i_pointeri_pointer将将i的地址的地址存到这里存到这里间接存取间接存取i_pointer=&i;i_pointer=&i;*i_pointer=*i_pointer=5050;5050i i200032000i_pointeri_pointer*i_pointer*i_pointer20003直接存取直接存取间接存取间接存取为了表示将数值送到变量中,可以有两种表达方法
5、:为了表示将数值送到变量中,可以有两种表达方法:(1)(1)将将3 3直接送到变量直接送到变量i i所标识的单元中,例如:所标识的单元中,例如:i=3;i=3;(2)(2)将将3 3送到变量送到变量i_pointeri_pointer所指向的单元(即变量所指向的单元(即变量i i的存储单的存储单元),例如:元),例如:*i_pointer=3;*i_pointer=3;其中其中*i_pointer*i_pointer表示表示i_pointeri_pointer指向指向的对象的对象指向就是通过地址来体现的指向就是通过地址来体现的假设假设i_pointeri_pointer中的值是变量的地址中的值
6、是变量的地址(2000)(2000),这样就在,这样就在i_pointeri_pointer和变量之间建立起一种联系,即通过和变量之间建立起一种联系,即通过i_pointeri_pointer能知道能知道i i的地址,从而找到变量的地址,从而找到变量i i的内存单元的内存单元由于通过地址能找到所需的变量单元,因此说,地址指由于通过地址能找到所需的变量单元,因此说,地址指向该变量单元向该变量单元将地址形象化地称为将地址形象化地称为“指针指针”。意思是通过它能找到以。意思是通过它能找到以它为地址的内存单元它为地址的内存单元一个变量的一个变量的地址地址称为该变量的称为该变量的“指针指针”例如,地址例
7、如,地址20002000是变量的指针是变量的指针如果有一个变量专门用来存放另一变量的地址(即指针),如果有一个变量专门用来存放另一变量的地址(即指针),则它称为则它称为“指针变量指针变量”i_pointeri_pointer就是一个指针变量。指针变量就是地址变量,用来就是一个指针变量。指针变量就是地址变量,用来存放地址的变量,指針变量的值是地址(即指针)存放地址的变量,指針变量的值是地址(即指针)“指针指针”和和“指针变量指针变量”是是不同的不同的概念概念可以说变量可以说变量i i的指针是的指针是20002000,而不能说,而不能说i i的指针变量是的指针变量是20002000指针是一个地址,
8、而指针变量是存放地址的变量指针是一个地址,而指针变量是存放地址的变量定义指针变量定义指针变量定义指针变量的一般形式为:定义指针变量的一般形式为:类型类型 *指针变量名指针变量名;其中,其中,*表示这是一个指针变量,变量名即为定义的指针变表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型量名,类型说明符表示本指针变量所指向的变量的数据类型如:如:int*pointer_1,*pointer_2;int*pointer_1,*pointer_2;uintint是是为为指针变量指定的指针变量指定的“基类型基类型”u基类型指定指针变量可指向的变量类型基类型
9、指定指针变量可指向的变量类型u如如pointer_1pointer_1可以指向整型变量,但不能指向浮点型变量可以指向整型变量,但不能指向浮点型变量如:如:int*p1;int*p1;表示表示p1p1是一个指针变量,它的值是某个整型变量的地址。是一个指针变量,它的值是某个整型变量的地址。或者说或者说p1p1指向一个整型变量。至于指向一个整型变量。至于p1p1究竟指向哪一个整型变量,究竟指向哪一个整型变量,应由向应由向p1p1赋予的地址来决定赋予的地址来决定。引用指针变量引用指针变量n在引用指针变量时,可能有三种情况:在引用指针变量时,可能有三种情况:给指针变量赋值。如:给指针变量赋值。如:p=&
10、a;p=&a;引用指针变量指向的变量引用指针变量指向的变量。如如有有 p=&a;*p=1;p=&a;*p=1;则执行则执行printf(“%d”,*p);printf(“%d”,*p);将输出将输出1 1引用指针变量的值。如:引用指针变量的值。如:printf(“%o”,p);printf(“%o”,p);使使p指向指向a*p相当于相当于a以八进制输以八进制输出出a的地址的地址要熟练掌握两个有关的运算符:要熟练掌握两个有关的运算符:(1)(1)取地址运算符。取地址运算符。&a&a是变量是变量a a的地址的地址(2)*(2)*指针运算符(指针运算符(“间接访问间接访问”运算符)运算符)如果如果:
11、p p指向变量指向变量a a,则则*p p就代表就代表a a。k=*p;(k=*p;(把把a a的值的值赋给赋给k)k)*p=1;(*p=1;(把把1 1赋给赋给a)a)设有指向整型变量的指针变量设有指向整型变量的指针变量p p,如要把整型变量,如要把整型变量a a 的地址赋予的地址赋予p p可以有以下两种方式:可以有以下两种方式:1.1.指针变量初始化的方法指针变量初始化的方法 int a;int a;int*p=&a;int*p=&a;2.2.赋值语句的方法赋值语句的方法 int a;int a;int*p;int*p;p=&a;p=&a;注:注:1.1.不允许把一个数赋予指针变量,故下面
12、的赋值是错误的:不允许把一个数赋予指针变量,故下面的赋值是错误的:int*p;int*p;p=1000;p=1000;2.2.被赋值的指针变量前不能再加被赋值的指针变量前不能再加“*”*”说明符,说明符,如写为如写为*p=&a*p=&a 也是错误的。也是错误的。假设假设:int i=200,x;int i=200,x;int*ip;int*ip;我们定义了两个整型变量我们定义了两个整型变量i,x,i,x,还定义了一个指向整型数的指针变量还定义了一个指向整型数的指针变量ip ip。i,xi,x中可存放整数中可存放整数,而而ip ip中只能存放整型变量的地址。我们可以把中只能存放整型变量的地址。我
13、们可以把i i的的地址赋给地址赋给ip:ip=&i;ip:ip=&i;此时指针变量此时指针变量ip ip指向整型变量指向整型变量i,i,假设变量假设变量i i的地址为的地址为1800,1800,这个赋值这个赋值可形象理解为下图所示的联系。可形象理解为下图所示的联系。以后我们便可以通过指针变量以后我们便可以通过指针变量ip ip间接访问变量间接访问变量i,i,例如例如:x=*ip;x=*ip;运算符运算符*访问以访问以ip ip为地址的存储区域为地址的存储区域,而而ip ip中存放的是变量中存放的是变量i i的地址的地址,因此因此,*ip,*ip访问的是地址为访问的是地址为18001800的存储
14、区域的存储区域(因为是整数因为是整数,实际上是从实际上是从18001800开始的两开始的两个字节个字节),),它就是它就是i i所占用的存储区域所占用的存储区域,所以上面的赋值表达式等价于所以上面的赋值表达式等价于 x=i;x=i;另外另外,指针变量和一般变量一样指针变量和一般变量一样,存放在它们之中的值是可以改变的存放在它们之中的值是可以改变的,也就是说可以改变它们的指向也就是说可以改变它们的指向,假设假设int i,j,*p1,*p2;int i,j,*p1,*p2;i=a;i=a;j=b;j=b;p1=&i;p1=&i;p2=&j;p2=&j;则建立如下图所示的联系则建立如下图所示的联系
15、:这时赋值表达式这时赋值表达式:p2=p1p2=p1就使就使p2p2与与p1p1指向同一对象指向同一对象i,i,此时此时*p2*p2就等价于就等价于i,i,而不是而不是j,j,图所示图所示:如果执行如下表达式如果执行如下表达式:*p2=*p1;*p2=*p1;则表示把则表示把p1p1指向的内容赋给指向的内容赋给p2p2所指的区域所指的区域,此时就变成图所示此时就变成图所示:例:例:输入输入a a和和b b两个整数,按先大后小的顺序输出两个整数,按先大后小的顺序输出a a和和b b。n解题思路:用指针方法来处理这个问题。不交换整型变量解题思路:用指针方法来处理这个问题。不交换整型变量的值,而是交
16、换两个指针变量的值。的值,而是交换两个指针变量的值。#include#include int main()int main()int*p1,*p2,*p,a,b;int*p1,*p2,*p,a,b;printf(“integer numbers:);printf(“integer numbers:);scanf(“%d,%d”,&a,&b);scanf(“%d,%d”,&a,&b);p1=&a;p2=&b;p1=&a;p2=&b;if(ab)if(ab)p=p1;p1=p2;p2=p;p=p1;p1=p2;p2=p;printf(“a=%d,b=%dn”,a,b);printf(“a=%d,b
17、=%dn”,a,b);printf(“%d,%dn”,*p1,*p2);printf(“%d,%dn”,*p1,*p2);return 0;return 0;abp1p2p59&a&b成立成立#include#include int main()int main()int*p1,*p2,*p,a,b;int*p1,*p2,*p,a,b;printf(“integer numbers:);printf(“integer numbers:);scanf(“%d,%d”,&a,&b);scanf(“%d,%d”,&a,&b);p1=&a;p2=&b;p1=&a;p2=&b;if(ab)if(ab)p
18、=p1;p1=p2;p2=p;p=p1;p1=p2;p2=p;printf(“a=%d,b=%dn”,a,b);printf(“a=%d,b=%dn”,a,b);printf(“%d,%dn”,*p1,*p2);printf(“%d,%dn”,*p1,*p2);return 0;return 0;abp1p2p59&a&b&b&a#include#include int main()int main()int*p1,*p2,*p,a,b;int*p1,*p2,*p,a,b;printf(“integer numbers:);printf(“integer numbers:);scanf(“%d
19、,%d”,&a,&b);scanf(“%d,%d”,&a,&b);p1=&a;p2=&b;p1=&a;p2=&b;if(ab)if(ab)p=p1;p1=p2;p2=p;p=p1;p1=p2;p2=p;printf(“a=%d,b=%dn”,a,b);printf(“a=%d,b=%dn”,a,b);printf(“%d,%dn”,*p1,*p2);printf(“%d,%dn”,*p1,*p2);return 0;return 0;abp1p2p59&a&b&b&a注意注意:ua a和和b b的值并未交换,它们仍保持原值的值并未交换,它们仍保持原值u但但p1p1和和p2p2的值改变了。的值改
20、变了。p1p1的值原为的值原为&a&a,后来变成,后来变成&b&b,p2p2原值为原值为&b&b,后来变成,后来变成&a&au这样在输出这样在输出*p1*p1和和*p2*p2时,实际上是输出变量时,实际上是输出变量b b和和a a的值,的值,所以先输出所以先输出9 9,然后输出,然后输出5 5指针变量作为函数参数指针变量作为函数参数例例:题目要求同上例,即对输入的两个整数按大小顺序输出。题目要求同上例,即对输入的两个整数按大小顺序输出。现用函数处理,而且用指针类型的数据作函数参数。现用函数处理,而且用指针类型的数据作函数参数。解题思路:定义一个函数解题思路:定义一个函数swapswap,将指向
21、两个整型变量的指针变量作为实参传,将指向两个整型变量的指针变量作为实参传递给递给swapswap函数的形参指针变量,在函数中通过指针实现交换两个变量的值。函数的形参指针变量,在函数中通过指针实现交换两个变量的值。#include#include int main()int main()void swap(int*p1,int*p2);void swap(int*p1,int*p2);int a,b;int*pointer_1,*pointer_2;int a,b;int*pointer_1,*pointer_2;printf(please enter a and b:);printf(plea
22、se enter a and b:);scanf(“%d,%d”,&a,&b);scanf(“%d,%d”,&a,&b);pointer_1=&a;pointer_1=&a;pointer_2=&b;pointer_2=&b;if(ab)swap(pointer_1,pointer_2);if(ab)swap(pointer_1,pointer_2);printf(“max=%d,min=%dn”,a,b);printf(“max=%d,min=%dn”,a,b);return 0;return 0;pointer_1a&a5pointer_2b&b9void swap(int*p1,int*
23、p2)void swap(int*p1,int*p2)int temp;int temp;temp=*p1;temp=*p1;*p1=*p2;*p1=*p2;*p2=temp;*p2=temp;abpointer_159&a&bpointer_2p1&ap2&b95n如果想通过函数调用得到个要改变的值:如果想通过函数调用得到个要改变的值:在主调函数中设个变量,用个指针变量指向它们在主调函数中设个变量,用个指针变量指向它们 设计一个函数,有设计一个函数,有n n个指针形参。在这个函数中改变这个指针形参。在这个函数中改变这个形参的值个形参的值 在主调函数中调用这个函数,在调用时将这在主调函数中调用
24、这个函数,在调用时将这n n个指针变个指针变量作实参,将它们的地址传给该函数的形参量作实参,将它们的地址传给该函数的形参 在执行该函数的过程中,通过形参指针变量,改变它在执行该函数的过程中,通过形参指针变量,改变它们所指向的个变量的值们所指向的个变量的值主调函数中就可以使用这些改变了值的变量主调函数中就可以使用这些改变了值的变量n注意:函数的调用可以(而且只可以)得到一个返回值(即注意:函数的调用可以(而且只可以)得到一个返回值(即函数值),而使用指针变量作参数,可以得到多个变化了的函数值),而使用指针变量作参数,可以得到多个变化了的值。如果不用指针变量是难以做到这一点的。值。如果不用指针变量
25、是难以做到这一点的。n要善于利用指针法。要善于利用指针法。例:输入例:输入3 3个整数个整数a,b,ca,b,c,要求按由大到小的顺序将它们输出。用,要求按由大到小的顺序将它们输出。用函数实现。函数实现。#include int main()void exchange(int*q1,int*q2,int*q3);int a,b,c,*p1,*p2,*p3;scanf(%d,%d,%d,&a,&b,&c);p1=&a;p2=&b;p3=&c;exchange(p1,p2,p3);printf(“%d,%d,%dn,a,b,c);return 0;调用结束后不会调用结束后不会改变指针的指向改变指针
26、的指向void exchange(int*q1,int*q2,int*q3)void swap(int*pt1,int*pt2);if(*q1*q2)swap(q1,q2);if(*q1*q3)swap(q1,q3);if(*q2*q3)swap(q2,q3);void swap(int*pt1,int*pt2)int temp;temp=*pt1;*pt1=*pt2;*pt2=temp;交换指针指交换指针指向的变量值向的变量值二、数组指针和指向数组的指针变量二、数组指针和指向数组的指针变量指向数组元素的指针指向数组元素的指针 通过指针引用数组元素通过指针引用数组元素 数组名做函数参数数组名做
27、函数参数指向多维数组的指针和指针变量指向多维数组的指针和指针变量指向数组元素的指针指向数组元素的指针一个数组是由连续的一块内存单元组成的。数组名就是这块连续一个数组是由连续的一块内存单元组成的。数组名就是这块连续内存单元的首地址。一个数组也是由各个数组元素内存单元的首地址。一个数组也是由各个数组元素(下标变量下标变量)组组成的。每个数组元素按其类型不同占有几个连续的内存单元。一成的。每个数组元素按其类型不同占有几个连续的内存单元。一个数组元素的首地址也是指它所占有的几个内存单元的首地址。个数组元素的首地址也是指它所占有的几个内存单元的首地址。定义一个指向数组元素的指针变量的方法,与以前介绍的指
28、针定义一个指向数组元素的指针变量的方法,与以前介绍的指针变量相同。变量相同。数组指针变量说明的一般形式为:数组指针变量说明的一般形式为:类型说明符类型说明符 *指针变量名;指针变量名;例如:例如:int a10 int a10;/*/*定义定义a a为包含为包含1010个整型数据的数组个整型数据的数组*/*/int*pint*p;/*/*定义定义p p为指向整型变量的指针为指向整型变量的指针*/*/应当注意,因为数组为应当注意,因为数组为intint型,所以指针变量也应为指向型,所以指针变量也应为指向intint型型的指针变量。下面是对指针变量赋值:的指针变量。下面是对指针变量赋值:p=&a0
29、;p=&a0;把把a0a0元素的地址赋给指针变量元素的地址赋给指针变量p p。也就是说,。也就是说,p p指向指向a a数组的数组的第第0 0号元素。号元素。C C语言规定,数组名代表数组的首地址,也就是第语言规定,数组名代表数组的首地址,也就是第0 0号元素的地址。号元素的地址。因此,下面两个语句等价:因此,下面两个语句等价:p=&a0;p=&a0;p=a;p=a;在定义指针变量时可以赋给初值:在定义指针变量时可以赋给初值:int*p=&a0;int*p=&a0;它等效于:它等效于:int*p;int*p;p=&a0;p=&a0;当然定义时也可以写成:当然定义时也可以写成:int*p=a;i
30、nt*p=a;从图中我们可以看出有以下关系:从图中我们可以看出有以下关系:p,a,&a0 p,a,&a0均指向同一单元,它们是数组均指向同一单元,它们是数组a a的首地址,也是的首地址,也是0 0 号元号元素素a0a0的首地址。应该说明的是的首地址。应该说明的是p p是变量,而是变量,而a,&a0a,&a0都是常量。都是常量。通过指针引用数组元素通过指针引用数组元素C C语言规定:如果指针变量语言规定:如果指针变量p p已指向数组中的一个元素,则已指向数组中的一个元素,则p+1p+1指向同一数组中的下一个元素。指向同一数组中的下一个元素。引入指针变量后,就可以用两种方法来访问数组元素了。引入指
31、针变量后,就可以用两种方法来访问数组元素了。如果如果p p的初值为的初值为&a0,&a0,则:则:1.p+i1.p+i和和a+ia+i就是就是aiai的地址,或者说它们指向的地址,或者说它们指向a a数组的第数组的第i i个元素。个元素。2.*(p+i)2.*(p+i)或或*(a+i)*(a+i)就是就是p+ip+i或或a+ia+i所指向的数组所指向的数组元素,即元素,即aiai。例如,。例如,*(p+5)*(p+5)或或*(a+5)*(a+5)就是就是a5a5。3.3.指向数组的指针变量也可以带下标,如指向数组的指针变量也可以带下标,如pipi与与*(p+i)*(p+i)等价。等价。根据以上
32、叙述,引用一个数组元素可以用:根据以上叙述,引用一个数组元素可以用:l下标法,即用下标法,即用aiai形式访问数组元素。在前面介绍数组时都形式访问数组元素。在前面介绍数组时都是采用这种方法。是采用这种方法。l指针法,即采用指针法,即采用*(a+i)*(a+i)或或*(p+i)*(p+i)形式,用间接访问的方法来访形式,用间接访问的方法来访问数组元素,其中问数组元素,其中a a是数组名,是数组名,p p是指向数组的指针变量,其是指向数组的指针变量,其处值处值p=ap=a。1.1.输出数组中的全部元素。(下标法)输出数组中的全部元素。(下标法)main()main()int a10,i;int a
33、10,i;for(i=0;i10;i+)for(i=0;i10;i+)ai=i;ai=i;for(i=0;i5;i+)for(i=0;i5;i+)printf(a%d=%dn,i,ai);printf(a%d=%dn,i,ai);2.2.输出数组中的全部元素。(用指针变量指向元素)输出数组中的全部元素。(用指针变量指向元素)main()main()int a10,i,*p;int a10,i,*p;p=a;p=a;for(i=0;i10;i+)for(i=0;i10;i+)*(p+i)=i;*(p+i)=i;for(i=0;i10;i+)for(i=0;i10;i+)printf(a%d=%d
34、n,i,*(p+i);printf(a%d=%dn,i,*(p+i);3.3.输出数组中的全部元素。(通过数组名计算元素的地址,输出数组中的全部元素。(通过数组名计算元素的地址,找出元素的值)找出元素的值)main()main()int a10,i;int a10,i;for(i=0;i10;i+)for(i=0;i10;i+)*(a+i)=i;*(a+i)=i;for(i=0;i10;i+)for(i=0;i10;i+)printf(a%d=%dn,i,*(a+i);printf(a%d=%dn,i,*(a+i);如果有一个实参数组,想在函数中改变此数组的元素的值,如果有一个实参数组,想在函
35、数中改变此数组的元素的值,实参与形参的对应关系有以下种:实参与形参的对应关系有以下种:形参和实参都是数组名。形参和实参都是数组名。main()main()int a10;int a10;f(a,10)f(a,10)f(int x,int n)f(int x,int n)和指的是同一组数组。和指的是同一组数组。数组名做函数参数数组名做函数参数l实实参参数组,形参用指针变量。数组,形参用指针变量。main()main()int a10;int a10;f(a,10)f(a,10)f(int*x,int n)f(int*x,int n)l实参、实参、形形参都用指针变量。参都用指针变量。l实参为指针变
36、量,实参为指针变量,形形参为数组名。参为数组名。指向多维数组的指针和指针变量指向多维数组的指针和指针变量以二维数组为例:以二维数组为例:1.1.二维数组的地址二维数组的地址设有整型二维数组设有整型二维数组a34a34如下:如下:0 1 2 3 0 1 2 35 6 7 5 6 7 9 10 119 10 11它的定义为:它的定义为:int a34=0,1,2,3,4,5,6,7,8,9,10,11int a34=0,1,2,3,4,5,6,7,8,9,10,11设数组设数组a a的首地址为的首地址为10001000,各个下标变量的首地址及其值如下:,各个下标变量的首地址及其值如下:C C语言允
37、许把一个二维数组分解为多个一维数组来处理,因语言允许把一个二维数组分解为多个一维数组来处理,因此数组此数组a a可以分解为三个一维数组,即可以分解为三个一维数组,即a0,a1,a2.a0,a1,a2.每一个一维每一个一维数组又含有四个元素。数组又含有四个元素。那么那么a0a0数组,含有数组,含有a00,a01,a02,a03a00,a01,a02,a03四个元素。四个元素。从二维数组的角度来看,从二维数组的角度来看,a a是二维数组名,是二维数组名,a a代表整个二维数组的代表整个二维数组的首地址,也是二维数组首地址,也是二维数组0 0行的首地址,等于行的首地址,等于10001000。a+1a
38、+1代表第一行的代表第一行的首地址,等于首地址,等于1008.1008.a0 a0是第一个一维数组的数组名和首地址,因此也为是第一个一维数组的数组名和首地址,因此也为10001000。*(a+0)*(a+0)或或*a*a是与是与a0a0等效的。它表示一维数组等效的。它表示一维数组a00 a00 号元素的首地址,号元素的首地址,也为也为10001000。&a00&a00是二维数组是二维数组a a的的0 0行行0 0列元素首地址,同样是列元素首地址,同样是10001000。因此,因此,a a,a0a0,*(a+0)*(a+0),*a*a,&a00&a00是相等的。是相等的。同理,同理,a+1a+1
39、是二维数组是二维数组1 1行的首地址,等于行的首地址,等于10081008。a1a1是第二个一维是第二个一维数组的数组名和首地址,因此也为数组的数组名和首地址,因此也为10081008。&a10&a10是二维数组是二维数组a a的的1 1行行0 0列元素地址,也是列元素地址,也是10081008。因此因此a+1,a1,*(a+1),&a10a+1,a1,*(a+1),&a10是等同的。是等同的。由此可得出:由此可得出:a+ia+i,aiai,*(a+i)*(a+i),&ai0&ai0是等同的。是等同的。另外,另外,a0a0也可以看成是也可以看成是a0+0a0+0,是一维数组,是一维数组a0a0
40、的的0 0号元素号元素的首地址,而的首地址,而a0+1a0+1则是则是a0a0的的1 1号元素首地址,由此可得出号元素首地址,由此可得出ai+jai+j则是一维数组则是一维数组aiai的的j j号元素首地址,它等于号元素首地址,它等于&aij&aij。由由ai=*(a+i)ai=*(a+i)得得ai+j=*(a+i)+jai+j=*(a+i)+j。由于。由于*(a+i)+j(a+i)+j是二维数组是二维数组a a的的i i行行j j列元素的首地址,所以,该元素的值等于列元素的首地址,所以,该元素的值等于*(*(a+i)+j)(*(a+i)+j)。2.2.指向多维数组的指针变量指向多维数组的指针
41、变量 把二维数组把二维数组a a分解为一维数组分解为一维数组a0,a1,a2a0,a1,a2之后,设之后,设p p为指向二维数组为指向二维数组的指针变量。可定义为:的指针变量。可定义为:int(*p)4 int(*p)4它表示它表示p p是一个指针变量,它指向包含是一个指针变量,它指向包含4 4个元素的一维数组。若指向个元素的一维数组。若指向第一个一维数组第一个一维数组a0a0,其值等于,其值等于a,a0a,a0,或,或&a00&a00等。而等。而p+ip+i则指向则指向一维数组一维数组aiai。从前面的分析可得出。从前面的分析可得出*(p+i)+j*(p+i)+j是二维数组是二维数组i i行
42、行j j 列的元素列的元素的地址,而的地址,而*(*(p+i)+j)*(*(p+i)+j)则是则是i i行行j j列元素的值。列元素的值。二维数组指针变量说明的一般形式为:二维数组指针变量说明的一般形式为:类型说明符类型说明符 (*(*指针变量名指针变量名)长度长度 其中其中“类型说明符类型说明符”为所指数组的数据类型。为所指数组的数据类型。“*”*”表示其后的变量表示其后的变量是指针类型。是指针类型。“长度长度”表示二维数组分解为多个一维数组时,表示二维数组分解为多个一维数组时,一维数组的长度,也就是二维数组的列数。一维数组的长度,也就是二维数组的列数。应注意应注意“(*“(*指针变量名指针
43、变量名)”)”两边的括号不可少,如缺少括号则表示两边的括号不可少,如缺少括号则表示是指针数组是指针数组(本章后面介绍本章后面介绍),意义就完全不同了。,意义就完全不同了。三、字符串的指针和指向字符串的指针变量三、字符串的指针和指向字符串的指针变量字符串的表示形式字符串的表示形式使用字符串指针变量和字符数组的区别使用字符串指针变量和字符数组的区别在在C C语言中,可以用两种方法访问一个字符串。语言中,可以用两种方法访问一个字符串。(1 1)用字符数组存放一个字符串,然后输出该字符串。)用字符数组存放一个字符串,然后输出该字符串。例:例:main()main()char string=char s
44、tring=“I love China!”;I love China!”;printf(%sn,string);printf(%sn,string);(2 2)用字符串指针指向一个字符串。)用字符串指针指向一个字符串。例:例:main()main()char*string=”I love China!”;char*string=”I love China!”;printf(%sn,string);printf(%sn,string);字符串的表示形式字符串的表示形式字符串指针变量的定义说明与指向字符变量的指针变量说明是相同的。字符串指针变量的定义说明与指向字符变量的指针变量说明是相同的。只能按
45、对指针变量的赋值不同来区别。对指向字符变量的指针变量只能按对指针变量的赋值不同来区别。对指向字符变量的指针变量应赋予该字符变量的地址。应赋予该字符变量的地址。如:如:char c,*p=&c;char c,*p=&c;表示表示p p是一个指向字符变量是一个指向字符变量c c的指针变量。的指针变量。而:而:char*s=C Language;char*s=C Language;则表示则表示s s是一个指向字符串的指针变量。把字符串的首地址赋予是一个指向字符串的指针变量。把字符串的首地址赋予s s。例:输出字符串中例:输出字符串中n n个字符后的所有字符。个字符后的所有字符。main()main(
46、)char*ps=this is a book;char*ps=this is a book;int n=10;int n=10;ps=ps+n;ps=ps+n;printf(%sn,ps);printf(%sn,ps);在程序中对在程序中对psps初始化时,即把字符串首地址赋予初始化时,即把字符串首地址赋予psps,当,当ps=ps+10ps=ps+10之后,之后,psps指向字符指向字符“b”“b”,因此输出为,因此输出为bookbook。#include#include#include#includeint main()int main()void swap(char*p1,cha*p2
47、);void swap(char*p1,cha*p2);char str120,str231,str320;char str120,str231,str320;printf(“input three lines:n”);printf(“input three lines:n”);gets(str1);gets(str2);gets(str3);gets(str1);gets(str2);gets(str3);if(strcmp(str1,str2)0)swap(str1,str2);if(strcmp(str1,str2)0)swap(str1,str2);if(strcmp(str1,str
48、3)0)swap(str1,str3);if(strcmp(str1,str3)0)swap(str1,str3);if(strcmp(str2,str3)0)swap(str2,str3);if(strcmp(str2,str3)0)swap(str2,str3);printf(“the order is:n”);printf(“the order is:n”);printf(“%sn%sn%sn”,str1,str2,str3);printf(“%sn%sn%sn”,str1,str2,str3);return 0;return 0;例:输入例:输入3 3个字符串,按由小到大的顺序输出。个
49、字符串,按由小到大的顺序输出。void swap(char*p1,char*p2)void swap(char*p1,char*p2)char p20;char p20;strcpy(p,p1);strcpy(p1,p2);strcpy(p2,p);strcpy(p,p1);strcpy(p1,p2);strcpy(p2,p);使用字符串指针变量与字符数组的区别使用字符串指针变量与字符数组的区别 用字符数组和字符指针变量都可实现字符串的存储和运算。用字符数组和字符指针变量都可实现字符串的存储和运算。但是两者是有区别的。在使用时应注意以下几个问题:但是两者是有区别的。在使用时应注意以下几个问题:
50、1.1.字符串指针变量本身是一个变量,用于存放字符串的首字符串指针变量本身是一个变量,用于存放字符串的首地址。而字符串本身是存放在以该首地址为首的一块连续的地址。而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以内存空间中并以00作为串的结束。字符数组是由于若干作为串的结束。字符数组是由于若干个数组元素组成的,它可用来存放整个字符串个数组元素组成的,它可用来存放整个字符串。2.2.对字符串指针方式对字符串指针方式char*ps=C Language;char*ps=C Language;可以写为:可以写为:char*ps;ps=C Language;char*ps;ps=C Lang