C语言程序设计第九章善于利用指针_第1页
C语言程序设计第九章善于利用指针_第2页
C语言程序设计第九章善于利用指针_第3页
C语言程序设计第九章善于利用指针_第4页
C语言程序设计第九章善于利用指针_第5页
已阅读5页,还剩61页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

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_pointeri_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_pointeri_pointer表示表示i_pointeri_pointer指向指向的对象的对象指向就是通过地址来体现的指向就是通过地址来体现的假设假设i_pointeri_point

6、er中的值是变量的地址中的值是变量的地址(2000)(2000),这样就在,这样就在i_pointeri_pointer和变量之间建立起一种联系,即通过和变量之间建立起一种联系,即通过i_pointeri_pointer能知道能知道i i的地址,从而找到变量的地址,从而找到变量i i的内存单元的内存单元由于通过地址能找到所需的变量单元,因此说,地址指由于通过地址能找到所需的变量单元,因此说,地址指向该变量单元向该变量单元将地址形象化地称为将地址形象化地称为“指针指针”。意思是通过它能找到以。意思是通过它能找到以它为地址的内存单元它为地址的内存单元一个变量的一个变量的地址地址称为该变量的称为该变

7、量的“指针指针”例如,地址例如,地址20002000是变量的指针是变量的指针如果有一个变量专门用来存放另一变量的地址(即指针),如果有一个变量专门用来存放另一变量的地址(即指针),则它称为则它称为“指针变量指针变量”i_pointeri_pointer就是一个指针变量。指针变量就是地址变量,用就是一个指针变量。指针变量就是地址变量,用来存放地址的变量,指針变量的值是地址(即指针)来存放地址的变量,指針变量的值是地址(即指针)“指针指针”和和“指针变量指针变量”是是不同的概念不同的概念可以说变量可以说变量i i的指针是的指针是20002000,而不能说,而不能说i i的指针变量是的指针变量是20

8、002000指针是一个地址,而指针变量是存放地址的变量指针是一个地址,而指针变量是存放地址的变量定义指针变量定义指针变量定义指针变量的一般形式为:定义指针变量的一般形式为: 类型类型 * * 指针变量名指针变量名; ; 其中,其中,* *表示这是一个指针变量,变量名即为定义的指针变表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型量名,类型说明符表示本指针变量所指向的变量的数据类型如:如:int int * *pointer_1, pointer_1, * *pointer_2;pointer_2;uintint是为指针变量指定的是为指针变量指定的

9、“基类型基类型”u基类型指定指针变量可指向的变量类型基类型指定指针变量可指向的变量类型u如如pointer_1pointer_1可以指向整型变量,但不能指向浮点型变量可以指向整型变量,但不能指向浮点型变量如:如: int int * *p1;p1;表示表示p1p1是一个指针变量,它的值是某个整型变量的地址。是一个指针变量,它的值是某个整型变量的地址。或者说或者说p1p1指向一个整型变量。至于指向一个整型变量。至于p1p1究竟指向哪一个整型变量,究竟指向哪一个整型变量,应由向应由向p1p1赋予的地址来决定赋予的地址来决定。引用指针变量引用指针变量n在引用指针变量时,可能有三种情况:在引用指针变量

10、时,可能有三种情况:给指针变量赋值。如:给指针变量赋值。如:p=&a;p=&a;引用指针变量指向的变量。如有引用指针变量指向的变量。如有 p=&a; p=&a; * *p=1;p=1; 则执行则执行printf(“%d”,printf(“%d”,* *p); p); 将输出将输出1 1引用指针变量的值。如:引用指针变量的值。如:printf(“%o”,p);printf(“%o”,p);使使p指向指向a*p相当于相当于a以八进制输以八进制输出出a的地址的地址要熟练掌握两个有关的运算符:要熟练掌握两个有关的运算符:(1) (1) 取地址运算符。取地址运算符。 &a&a是变量是变量a a的地址的地

11、址(2) (2) * * 指针运算符(指针运算符(“间接访问间接访问”运算符)运算符) 如果:如果: p p指向变量指向变量a a,则,则* *p p就代表就代表a a。 k=k=* *p; (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 int * *p=&a;p=&a;2. 2.赋值语

12、句的方法赋值语句的方法 int a;int a; int int * *p; p; p=&a; p=&a;注:注:1. 1.不允许把一个数赋予指针变量,故下面的赋值是错误的:不允许把一个数赋予指针变量,故下面的赋值是错误的:int int * *p; p;p=1000;p=1000;2. 2.被赋值的指针变量前不能再加被赋值的指针变量前不能再加“* *”说明符,说明符, 如写为如写为* *p=&a p=&a 也是错误的。也是错误的。假设假设: : int i=200, x; int i=200, x; int int * *ip;ip;我们定义了两个整型变量我们定义了两个整型变量i,x,i,x

13、,还定义了一个指向整型数的指针变量还定义了一个指向整型数的指针变量ip ip。i,xi,x中可存放整数中可存放整数, ,而而ip ip中只能存放整型变量的地址。我们可以把中只能存放整型变量的地址。我们可以把i i的的地址赋给地址赋给ip: ip=&i;ip: ip=&i;此时指针变量此时指针变量ip ip指向整型变量指向整型变量i, i,假设变量假设变量i i的地址为的地址为1800,1800,这个赋值这个赋值可形象理解为下图所示的联系。可形象理解为下图所示的联系。以后我们便可以通过指针变量以后我们便可以通过指针变量ip ip间接访问变量间接访问变量i, i,例如例如: : x= x=* *i

14、p;ip;运算符运算符* *访问以访问以ip ip为地址的存储区域为地址的存储区域, ,而而ip ip中存放的是变量中存放的是变量i i的地址的地址, ,因因此此, ,* *ip ip访问的是地址为访问的是地址为18001800的存储区域的存储区域( (因为是整数因为是整数, ,实际上是从实际上是从18001800开始开始的两个字节的两个字节), ),它就是它就是i i所占用的存储区域所占用的存储区域, , 所以上面的赋值表达式等价于所以上面的赋值表达式等价于 x=i; x=i;另外另外, ,指针变量和一般变量一样指针变量和一般变量一样, ,存放在它们之中的值是可以改变的存放在它们之中的值是可

15、以改变的, ,也就是说可以改变它们的指向也就是说可以改变它们的指向, ,假设假设int i,j,int i,j,* *p1,p1,* *p2;p2; i=a; i=a; j=b; j=b;p1=&i;p1=&i;p2=&j;p2=&j;则建立如下图所示的联系则建立如下图所示的联系: :这时赋值表达式这时赋值表达式: :p2=p1p2=p1就使就使p2p2与与p1p1指向同一对象指向同一对象i, i,此时此时* *p2p2就等价于就等价于i, i,而不是而不是j, j,图所示图所示: :如果执行如下表达式如果执行如下表达式: : * *p2=p2=* *p1;p1;则表示把则表示把p1p1指向的

16、内容赋给指向的内容赋给p2p2所指的区域所指的区域, , 此时就变成图所示此时就变成图所示: : 例:例: 输入输入a a和和b b两个整数,按先大后小的顺序输出两个整数,按先大后小的顺序输出a a和和b b。解题思路:用指针方法来处理这个问题。不交换整型变量的解题思路:用指针方法来处理这个问题。不交换整型变量的值,而是交换两个指针变量的值。值,而是交换两个指针变量的值。#include #include int main()int main() int int * *p1,p1,* *p2,p2,* *p,a,b; p,a,b; printf(“integer numbers:); prin

17、tf(“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=%dn”,a,b); printf(“%d,%dn”, printf(“%d,%dn”,* *p1,p1,* *p2); p2); return 0; return 0; abp1p2p59&a&b成立成立#include

18、#include int main()int main() int int * *p1,p1,* *p2,p2,* *p,a,b; 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=%dn”,a,b

19、); printf(“%d,%dn”, printf(“%d,%dn”,* *p1,p1,* *p2); p2); return 0; return 0; abp1p2p59&a&b&b&a#include #include int main()int main() int int * *p1,p1,* *p2,p2,* *p,a,b; 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=&

20、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”, printf(“%d,%dn”,* *p1,p1,* *p2); p2); return 0; return 0; abp1p2p59&a&b&b&a注意注意: :ua a和和b b的值并未交换,它们仍保持原值的值并未交换,它们仍保持原值u但但p1p1和和p2p2的值改变了。的值改变了。p1p1的值原为的值原为&a&a,后来变成,后来变成&b&b,p

21、2p2原值为原值为&b&b,后来变成,后来变成&a&au这样在输出这样在输出* *p1p1和和* *p2p2时,实际上是输出变量时,实际上是输出变量b b和和a a的值,的值,所以先输出所以先输出9 9,然后输出,然后输出5 5指针变量作为函数参数指针变量作为函数参数例例: : 题目要求同上例,即对输入的两个整数按大小顺序输出。题目要求同上例,即对输入的两个整数按大小顺序输出。现用函数处理,而且用指针类型的数据作函数参数。现用函数处理,而且用指针类型的数据作函数参数。解题思路:定义一个函数解题思路:定义一个函数swapswap,将指向两个整型变量的指针变量作为实参传,将指向两个整型变量的指针变

22、量作为实参传递给递给swapswap函数的形参指针变量,在函数中通过指针实现交换两个变量的值。函数的形参指针变量,在函数中通过指针实现交换两个变量的值。#include #include int main()int main()void swap(int void swap(int * *p1,int p1,int * *p2); p2); int a,b; int int a,b; int* *pointer_1,pointer_1,* *pointer_2; pointer_2; printf(please enter a and b:); printf(please enter a an

23、d 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 voi

24、d swap(int * *p1,int p1,int * *p2) p2) int temp; int temp; temp= temp=* *p1; p1; * *p1=p1=* *p2;p2; * *p2=temp;p2=temp; abpointer_159&a&bpointer_2p1&ap2&b95如果想通过函数调用得到个要改变的值:如果想通过函数调用得到个要改变的值: 在主调函数中设个变量,用个指针变量指向它们在主调函数中设个变量,用个指针变量指向它们 设计一个函数,有设计一个函数,有n n个指针形参。在这个函数中改变这个指针形参。在这个函数中改变这个形参的值个形参的值 在主调函

25、数中调用这个函数,在调用时将这在主调函数中调用这个函数,在调用时将这n n个指针变个指针变量作实参,将它们的地址传给该函数的形参量作实参,将它们的地址传给该函数的形参 在执行该函数的过程中,通过形参指针变量,改变它在执行该函数的过程中,通过形参指针变量,改变它们所指向的个变量的值们所指向的个变量的值主调函数中就可以使用这些改变了值的变量主调函数中就可以使用这些改变了值的变量注意:函数的调用可以(而且只可以)得到一个返回值(即函注意:函数的调用可以(而且只可以)得到一个返回值(即函数值),而使用指针变量作参数,可以得到多个变化了的值数值),而使用指针变量作参数,可以得到多个变化了的值。如果不用指

26、针变量是难以做到这一点的。如果不用指针变量是难以做到这一点的。要善于利用指针法。要善于利用指针法。例:输入例:输入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); re

27、turn 0;调用结束后不会调用结束后不会改变指针的指向改变指针的指向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; 交换指针指交换指针指向的变量值向的变量值二、数组指针和指向数组的指针变量二、数组指针和指向数组的

28、指针变量指向数组元素的指针指向数组元素的指针 通过指针引用数组元素通过指针引用数组元素 数组名做函数参数数组名做函数参数指向多维数组的指针和指针变量指向多维数组的指针和指针变量指向数组元素的指针指向数组元素的指针一个数组是由连续的一块内存单元组成的。数组名就是这块连续一个数组是由连续的一块内存单元组成的。数组名就是这块连续内存单元的首地址。一个数组也是由各个数组元素内存单元的首地址。一个数组也是由各个数组元素( (下标变量下标变量) )组组成的。每个数组元素按其类型不同占有几个连续的内存单元。一成的。每个数组元素按其类型不同占有几个连续的内存单元。一个数组元素的首地址也是指它所占有的几个内存单

29、元的首地址。个数组元素的首地址也是指它所占有的几个内存单元的首地址。定义一个指向数组元素的指针变量的方法,与以前介绍的指针定义一个指向数组元素的指针变量的方法,与以前介绍的指针变量相同。变量相同。数组指针变量说明的一般形式为:数组指针变量说明的一般形式为:类型说明符类型说明符 * *指针变量名;指针变量名;例如:例如: int a10int a10; / /* *定义定义a a为包含为包含1010个整型数据的数组个整型数据的数组* */ /int int * *p p; / /* *定义定义p p为指向整型变量的指针为指向整型变量的指针* */ /应当注意,因为数组为应当注意,因为数组为int

30、int型,所以指针变量也应为指向型,所以指针变量也应为指向intint型型的指针变量。下面是对指针变量赋值:的指针变量。下面是对指针变量赋值:p=&a0;p=&a0;把把a0a0元素的地址赋给指针变量元素的地址赋给指针变量p p。也就是说,。也就是说,p p指向指向a a数组的数组的第第0 0号元素。号元素。c c语言规定,数组名代表数组的首地址,也就是第语言规定,数组名代表数组的首地址,也就是第0 0号元素的地址。号元素的地址。因此,下面两个语句等价:因此,下面两个语句等价:p=&a0;p=&a0;p=a;p=a;在定义指针变量时可以赋给初值:在定义指针变量时可以赋给初值:int int *

31、 *p=&a0;p=&a0;它等效于:它等效于:int int * *p; p; p=&a0;p=&a0;当然定义时也可以写成:当然定义时也可以写成: int int * *p=a;p=a;从图中我们可以看出有以下关系:从图中我们可以看出有以下关系: p,a,&a0p,a,&a0均指向同一单元,它们是数组均指向同一单元,它们是数组a a的首地址,也是的首地址,也是0 0 号元号元素素a0a0的首地址。应该说明的是的首地址。应该说明的是p p是变量,而是变量,而a,&a0a,&a0都是常量。都是常量。通过指针引用数组元素通过指针引用数组元素c c语言规定:如果指针变量语言规定:如果指针变量p p

32、已指向数组中的一个元素,则已指向数组中的一个元素,则p+1p+1指向同一数组中的下一个元素。指向同一数组中的下一个元素。引入指针变量后,就可以用两种方法来访问数组元素了。引入指针变量后,就可以用两种方法来访问数组元素了。如果如果p p的初值为的初值为&a0,&a0,则:则:1.p+i1.p+i和和a+ia+i就是就是aiai的地址,或者说它们指向的地址,或者说它们指向a a数组的第数组的第i i个元素。个元素。2. 2.* *(p+i)(p+i)或或* *(a+i)(a+i)就是就是p+ip+i或或a+ia+i所指向的数组所指向的数组元素,即元素,即aiai。例如,。例如,* *(p+5)(p

33、+5)或或* *(a+5)(a+5)就是就是a5a5。3. 3.指向数组的指针变量也可以带下标,如指向数组的指针变量也可以带下标,如pipi与与* *(p+i)(p+i)等价。等价。根据以上叙述,引用一个数组元素可以用:根据以上叙述,引用一个数组元素可以用:l下标法,即用下标法,即用aiai形式访问数组元素。在前面介绍数组时都形式访问数组元素。在前面介绍数组时都是采用这种方法。是采用这种方法。l指针法,即采用指针法,即采用* *(a+i)(a+i)或或* *(p+i)(p+i)形式,用间接访问的方法来访形式,用间接访问的方法来访问数组元素,其中问数组元素,其中a a是数组名,是数组名,p p是

34、指向数组的指针变量,其是指向数组的指针变量,其处值处值p=ap=a。1. 1.输出数组中的全部元素。(下标法)输出数组中的全部元素。(下标法)main()main() int a10,i; int a10,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, int

35、 a10,i,* *p; 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=%dn,i, printf(a%d=%dn,i,* *(p+i);(p+i); 3. 3.输出数组中的全部元素。(通过数组名计算元素的地址,输出数组中的全部元素。(通过数组名计算元素的地址,找出元素的值)找出元素的值)main()main() int a10,i; int a10,i; for(i=0;i10;i+) for(i=0;i10;i+) * *

36、(a+i)=i;(a+i)=i; for(i=0;i10;i+) for(i=0;i10;i+) printf(a%d=%dn,i, printf(a%d=%dn,i,* *(a+i);(a+i); 如果有一个实参数组,想在函数中改变此数组的元素的值,如果有一个实参数组,想在函数中改变此数组的元素的值,实参与形参的对应关系有以下种:实参与形参的对应关系有以下种:形参和实参都是数组名。形参和实参都是数组名。main()main()int a10;int a10; f(a,10) f(a,10) f(int x ,int n)f(int x ,int n) 和指的是同一组数组。和指的是同一组数组。

37、数组名做函数参数数组名做函数参数l实参数组,形参用指针变量。实参数组,形参用指针变量。main()main()int a10;int a10; f(a,10) f(a,10) f(int f(int * *x,int n)x,int n) l实参、形参都用指针变量。实参、形参都用指针变量。l实参为指针变量,形参为数组名。实参为指针变量,形参为数组名。指向多维数组的指针和指针变量指向多维数组的指针和指针变量以二维数组为例:以二维数组为例:1. 1.二维数组的地址二维数组的地址设有整型二维数组设有整型二维数组a34a34如下:如下: 0 1 2 30 1 2 35 6 7 5 6 7 9 10 1

38、19 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语言允许把一个二维数组分解为多个一维数组来处理,因语言允许把一个二维数组分解为多个一维数组来处理,因此数组此数组a a可以分解为三个一维数组,即可以分解为三个一维数组,即a0,a1,a2.a0,a1,a2.每一个一维每一个一维数组又含有四个元素。数组又含有四个元素。那么那么a0a0数组,含有数组,

39、含有a00,a01,a02,a03a00,a01,a02,a03四个元素。四个元素。 从二维数组的角度来看,从二维数组的角度来看,a a是二维数组名,是二维数组名,a a代表整个二维数组的代表整个二维数组的首地址,也是二维数组首地址,也是二维数组0 0行的首地址,等于行的首地址,等于10001000。a+1a+1代表第一行的代表第一行的首地址,等于首地址,等于1008.1008. a0 a0是第一个一维数组的数组名和首地址,因此也为是第一个一维数组的数组名和首地址,因此也为10001000。* *(a+0)(a+0)或或* *a a是与是与a0a0等效的。它表示一维数组等效的。它表示一维数组a

40、00 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是二维数组是二维数组1 1行的首地址,等于行的首地址,等于10081008。a1a1是第二个一维是第二个一维数组的数组名和首地址,因此也为数组的数组名和首地址,因此也为10081008。&a10&a10是二维数组是二维数组a a的的1 1行行0 0列元素地址,也是列元素地址

41、,也是10081008。因此因此a+1,a1,a+1,a1,* *(a+1),&a10(a+1),&a10是等同的。是等同的。由此可得出:由此可得出:a+ia+i,aiai,* *(a+i)(a+i),&ai0&ai0是等同的。是等同的。 另外,另外,a0a0也可以看成是也可以看成是a0+0a0+0,是一维数组,是一维数组a0a0的的0 0号元素号元素的首地址,而的首地址,而a0+1a0+1则是则是a0a0的的1 1号元素首地址,由此可得出号元素首地址,由此可得出ai+jai+j则是一维数组则是一维数组aiai的的j j号元素首地址,它等于号元素首地址,它等于&aij&aij。由由ai=ai=

42、* *(a+i)(a+i)得得ai+j=ai+j=* *(a+i)+j(a+i)+j。由于。由于* *(a+i)+j(a+i)+j是二维数组是二维数组a a的的i i行行j j列元素的首地址,所以,该元素的值等于列元素的首地址,所以,该元素的值等于* *( (* *(a+i)+j)(a+i)+j)。2. 2.指向多维数组的指针变量指向多维数组的指针变量 把二维数组把二维数组a a分解为一维数组分解为一维数组a0,a1,a2a0,a1,a2之后,设之后,设p p为指向二维数组为指向二维数组的指针变量。可定义为:的指针变量。可定义为: int (int (* *p)4p)4它表示它表示p p是一个

43、指针变量,它指向包含是一个指针变量,它指向包含4 4个元素的一维数组。若指向个元素的一维数组。若指向第一个一维数组第一个一维数组a0a0,其值等于,其值等于a,a0a,a0,或,或&a00&a00等。而等。而p+ip+i则指向则指向一维数组一维数组aiai。从前面的分析可得出。从前面的分析可得出* *(p+i)+j(p+i)+j是二维数组是二维数组i i行行j j 列的元素列的元素的地址,而的地址,而* *( (* *(p+i)+j)(p+i)+j)则是则是i i行行j j列元素的值。列元素的值。二维数组指针变量说明的一般形式为:二维数组指针变量说明的一般形式为:类型说明符类型说明符 ( (*

44、 *指针变量名指针变量名) )长度长度 其中其中“类型说明符类型说明符”为所指数组的数据类型。为所指数组的数据类型。“* *”表示其后的变量表示其后的变量是指针类型。是指针类型。“长度长度”表示二维数组分解为多个一维数组时,表示二维数组分解为多个一维数组时,一维数组的长度,也就是二维数组的列数。一维数组的长度,也就是二维数组的列数。应注意应注意“( (* *指针变量名指针变量名)”)”两边的括号不可少,如缺少括号则表示两边的括号不可少,如缺少括号则表示是指针数组是指针数组( (本章后面介绍本章后面介绍) ),意义就完全不同了。,意义就完全不同了。三、字符串的指针和指向字符串的指针变量三、字符串

45、的指针和指向字符串的指针变量字符串的表示形式字符串的表示形式使用字符串指针变量和字符数组的区别使用字符串指针变量和字符数组的区别在在c c语言中,可以用两种方法访问一个字符串。语言中,可以用两种方法访问一个字符串。(1 1)用字符数组存放一个字符串,然后输出该字符串。)用字符数组存放一个字符串,然后输出该字符串。 例:例:main( )main( ) char string=“i love china!”; char string=“i love china!”; printf(%sn,string); printf(%sn,string); (2 2)用字符串指针指向一个字符串。)用字符串指

46、针指向一个字符串。 例:例: main()main() char char * *string=”i love china!”;string=”i love china!”; printf(%sn,string); printf(%sn,string); 字符串的表示形式字符串的表示形式字符串指针变量的定义说明与指向字符变量的指针变量说明是相同的。字符串指针变量的定义说明与指向字符变量的指针变量说明是相同的。只能按对指针变量的赋值不同来区别。对指向字符变量的指针变量只能按对指针变量的赋值不同来区别。对指向字符变量的指针变量应赋予该字符变量的地址。应赋予该字符变量的地址。如:如: char c,

47、char c,* *p=&c;p=&c;表示表示p p是一个指向字符变量是一个指向字符变量c c的指针变量。的指针变量。而:而: char char * *s=c language;s=c language;则表示则表示s s是一个指向字符串的指针变量。把字符串的首地址赋予是一个指向字符串的指针变量。把字符串的首地址赋予s s。例:输出字符串中例:输出字符串中n n个字符后的所有字符。个字符后的所有字符。main( )main( ) char char * *ps=this is a book;ps=this is a book; int n=10; int n=10; ps=ps+n; ps

48、=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 void swap(char * *p1,cha p1,cha * *p2);p2);char str120,str231,str320;char str120

49、,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,str3)0) swap(str1,str3);if(strcmp(str1,str3)0) swap(str1,str3);if(

50、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个字符串,按由小到大的顺序输出。个字符串,按由小到大的顺序输出。void swap(char void swap(char * *p1,char p1

51、,char * *p2)p2)char p20;char p20;strcpy(p,p1); strcpy(p1,p2); strcpy(p2,p); strcpy(p,p1); strcpy(p1,p2); strcpy(p2,p); 使用字符串指针变量与字符数组的区别使用字符串指针变量与字符数组的区别 用字符数组和字符指针变量都可实现字符串的存储和运算。用字符数组和字符指针变量都可实现字符串的存储和运算。但是两者是有区别的。在使用时应注意以下几个问题:但是两者是有区别的。在使用时应注意以下几个问题: 1. 1.字符串指针变量本身是一个变量,用于存放字符串的首字符串指针变量本身是一个变量,用

52、于存放字符串的首地址。而字符串本身是存放在以该首地址为首的一块连续的地址。而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以内存空间中并以00作为串的结束。字符数组是由于若干作为串的结束。字符数组是由于若干个数组元素组成的,它可用来存放整个字符串个数组元素组成的,它可用来存放整个字符串。 2. 2.对字符串指针方式对字符串指针方式char char * *ps=c language;ps=c language;可以写为:可以写为: char char * *ps; ps=c language;ps; ps=c language;而对数组方式:而对数组方式: static char s

53、t=c language;static char st=c language;不能写为:不能写为: char st20; st=c language;char st20; st=c language;而只能对字符数组的各元素逐个赋值。而只能对字符数组的各元素逐个赋值。四、指针数组和指向指针的指针四、指针数组和指向指针的指针指针数组的概念指针数组的概念 指向指针的指针指向指针的指针字符串的表示形式字符串的表示形式指针数组的概念指针数组的概念一个数组的元素值为指针则是指针数组。一个数组的元素值为指针则是指针数组。 指针数组是一组有序的指针数组是一组有序的指针的集合。指针的集合。指针数组的所有元素都

54、必须是具有相同存储类型和指向相同数据指针数组的所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。类型的指针变量。 指针数组说明的一般形式为:指针数组说明的一般形式为: 类型说明符类型说明符 * *数组名数组名 数组长度数组长度 其中类型说明符为指针值所指向的变量的类型。其中类型说明符为指针值所指向的变量的类型。例如:例如:int int * *pa3pa3表示表示papa是一个指针数组,它有三个数组元素,每个元素值都是是一个指针数组,它有三个数组元素,每个元素值都是一个指针,指向整型变量。一个指针,指向整型变量。应该注意指针数组和二维数组指针变量的区别。这两者虽然都应该注意指针数组

55、和二维数组指针变量的区别。这两者虽然都可用来表示二维数组,但是其表示方法和意义是不同的。可用来表示二维数组,但是其表示方法和意义是不同的。二维数组指针变量是单个的变量,其一般形式中二维数组指针变量是单个的变量,其一般形式中( (* *指针变量指针变量名名) )两边的括号不可少。而指针数组类型表示的是多个指针两边的括号不可少。而指针数组类型表示的是多个指针( (一一组有序指针组有序指针) )在一般形式中在一般形式中 * *指针数组名指针数组名 两边不能有括号。两边不能有括号。例如:例如: int (int (* *p)3;p)3;表示一个指向二维数组的指针变量。该二维数组的列数为表示一个指向二维

56、数组的指针变量。该二维数组的列数为3 3或或分解为一维数组的长度为分解为一维数组的长度为3 3。 int int * *p3p3表示表示p p是一个指针数组,有三个下标变量是一个指针数组,有三个下标变量p0p0,p1p1,p2p2均为指均为指针变量针变量。指向指针的指针指向指针的指针 从下图可以看到,从下图可以看到,namename是一个指针数组,它的每一个元素是是一个指针数组,它的每一个元素是一个指针型数据,其值为地址。一个指针型数据,其值为地址。namename是一个数组,它的每一个元素是一个数组,它的每一个元素都有相应的地址。数组名都有相应的地址。数组名namename代表该指针数组的首

57、地址。代表该指针数组的首地址。name+1name+1是是maneimanei的地址。的地址。name+1name+1就是指向指针型数据的指针就是指向指针型数据的指针(地址)。还可以设置一个指针变量(地址)。还可以设置一个指针变量p p,使它指向指针数组元素。,使它指向指针数组元素。p p就是指向指针型数据的指针变量。就是指向指针型数据的指针变量。 如果一个指针变量存放的又是另一个指针变量的地址,则称这个如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。指针变量为指向指针的指针变量。char char * * *p; p;p p前面有两个前面有两个* *号号

58、, ,相当于相当于* *( (* *p)p)。显然。显然* *p p是指针变量的定义形式,是指针变量的定义形式,如果没有最前面的如果没有最前面的* *,那就是定义了一个指向字符数据的指针变,那就是定义了一个指向字符数据的指针变量。现在它前面又有一个量。现在它前面又有一个* *号,表示指针变量号,表示指针变量p p是指向一个字符是指向一个字符指针型变量的。指针型变量的。* *p p就是就是p p所指向的另一个指针变量。所指向的另一个指针变量。如果有:如果有:p=name+2;p=name+2;printf(“%on”,printf(“%on”,* *p);p);printf(“%sn”,prin

59、tf(“%sn”,* *p);p);则第一个则第一个printfprintf函数语句输出函数语句输出name2name2的值(它是一个地址),的值(它是一个地址),第二个第二个printfprintf函数语句以字符串形式(函数语句以字符串形式(%s%s)输出字符串)输出字符串“great great wall”wall”。指针变量可以进行某些运算,但其运算的种类是有限的。它只能指针变量可以进行某些运算,但其运算的种类是有限的。它只能进行赋值运算和部分算术运算及关系运算。进行赋值运算和部分算术运算及关系运算。1. 1.指针运算符指针运算符l取地址运算符取地址运算符&:&:取地址运算符取地址运算符

60、& &是单目运算符,其结合性为自右是单目运算符,其结合性为自右至左,其功能是取变量的地址。在至左,其功能是取变量的地址。在scanfscanf函数及前面介绍指针变量函数及前面介绍指针变量赋值中,我们已经了解并使用了赋值中,我们已经了解并使用了& &运算符。运算符。l取内容运算符取内容运算符* *: :取内容运算符取内容运算符* *是单目运算符,其结合性为自右是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量。在至左,用来表示指针变量所指的变量。在* *运算符之后跟的变量必运算符之后跟的变量必须是指针变量。须是指针变量。需要注意的是指针运算符需要注意的是指针运算符* *和指针变量说明中

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论