第十章指针 (C语言培训课讲义)_第1页
第十章指针 (C语言培训课讲义)_第2页
第十章指针 (C语言培训课讲义)_第3页
第十章指针 (C语言培训课讲义)_第4页
第十章指针 (C语言培训课讲义)_第5页
已阅读5页,还剩40页未读 继续免费阅读

下载本文档

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

文档简介

1、第十章 指针指针变量指针与数组的关系指针与字符串指针数组及指向指针的指针指针的基本概念指针的基本概念直接访问与间接访问v直接访问:按变量地址存取变量值v间接访问:通过存放变量地址的变量去访问变量.2000200420062005整型变量i3200120022003main() int i; i=3; printf(“%d”,i); 这种访问变量的方式称为直接访问 与直接访问相对应,对变量访问的另一种方式是间接访问.20002004200620053200120022003ip2000如上图所示,当要访问 i 时,先访问变量 p 所在的存储单元,从中得到变量i所在的存储单元2000,然后通过这个

2、地址访问变量 i 。在上述描述中,有两个基本的操作要完成:怎样把变量 i i 的地址赋给变量 p 。怎样通过变量 p p 来访问(操作)变量 i i 。为此,C中有两个专门的运算符来完成上述两个操作&:取地址运算符* :指针运算符(间接访问运算符),该运算符将其后的操作数当成地址对待,并访问该地址。例如,在上图中,对于变量 p ,若欲使其中的值为变量 i 的地址,则可用操作 p=&i ;经此操作后,*p即相当于变量i。对于变量p,因为其特殊性,因此被称为指针变量,简称指针。其实所谓指针就是地址,而指针变量则是专门存放地址值的一种变量。指针、指针变量指针:一个变量的地址指针变量:

3、专门存放变量地址的变量定义: 数据类型 *指针名; 如 :int *p;说明:类型标识符说明了指针变量所指向的变量类型。一个指针变量只能指向规定类型的变量,如定义:int * p;则指针p只能指向整型变量。 定义指针变量时“ * ”不能少,但真正的指针变量是*号后面的指针变量名p ,不是*p指针变量定义后,变量值不确定,应用前必须先赋值例 main( ) int i=10; int *p; *p=i; printf(“%d”,*p); 危险!例 main( ) int i=10,k; int *p; p=&k; *p=i; printf(“%d”,*p); .2000200420062

4、005整型变量i10指针变量p200120022003随机指针变量中只能存放变量的地址,向其中进行直接赋值是不对的。如,若有定义:int * p,i; 则以下正确的操作是:则以下正确的操作是:p=100;p=&100;p=i;p=&i;对指针变量的操作 ,应使用运算符:&和*。读下程序:指针变量的使用指针变量的使用main()() int a,b,t , * p1,* p2; a=3;b=5; p1=&a; p2=&b; printf(“a=%d,b=%dn”,a,b); printf(“*p1=%d,*p2=%dn”,”,*p1,*p2); *p1=7

5、; *p2=9; printf(“%a=%d,b=%dn”,a,b);); 通过这个程序可以看到:通过这个程序可以看到:指针变量定义后,若要指针变量定义后,若要其和某个变量建立联系(指向该变量),可以通其和某个变量建立联系(指向该变量),可以通过过p1=&a的操作达到目的,的操作达到目的,如果有如果有p=&a,则,则*p1即指向变量即指向变量a ,*p即是变量即是变量a。例 输入两个数,并使其从大到小输出main() int *p1,*p2,*p,a,b; scanf(%d,%d,&a,&b); p1=&a; p2=&b; if(ab) p=p1

6、; p1=p2; p2=p; printf(a=%d,b=%dn,a,b); printf(max=%d,min=%dn,*p1,*p2);运行结果:a=5,b=9 max=9,min=5.指针变量p1 指针变量p20002008200220042006 指针变量p2 整型变量b 整型变量a5200692008200620082006l指针变量作为函数参数地址传递特点:共享内存,“双向”传递swap(int *p1, int *p2) int p; p=*p1; *p1=*p2; *p2=p;main() int a,b; int *pointer_1,*pointer_2; scanf(%d

7、,%d,&a,&b); pointer_1=&a; pointer_2=&b; if(ab)swap(pointer_1,pointer_2); printf(n%d,%dn,a,b);.20002008200A200220042006200C200E2010.59整型变量a 整型变量b(main)指针pointer_1指针pointer_220002002(swap)指针p1指针p2整型p5920002002COPY5例 将数从大到小输出swap(int *p1, int *p2) int p; p=*p1; *p1=*p2; *p2=p;main() int

8、 a,b; int *pointer_1,*pointer_2; scanf(%d,%d,&a,&b); pointer_1=&a; pointer_2=&b; if(ab)swap(pointer_1,pointer_2); printf(n%d,%dn,a,b);.20002008200A200220042006200C200E2010.59整型变量a 整型变量b(main)指针pointer_1指针pointer_22000200259例 将数从大到小输出运行结果:9,5地址传递指针与一维数组指向数组元素的指针变量如前所述,数组中的每一个元素都相当于一个单

9、独的变量。因此,同样可以用一个指针变量来指向数组中的元素。对于数组指针,从字面上理解,即是“数组的指针”,或说是“指向数组的指针”。而“变量x的指针中存放的其实是变量x的地址”,因此,“数组指针中存放的是数组的地址”,或者说“数组指针中存放的是数组的首地址,即数组中第一个元素的地址”。定义数组指针的方法与定义指针变量的方法相同,如: int a10int a10,* *p p;当p=p=&a0&a0时,我们称p为数组a的指针。由于在C中,数组名即代表数组的起始地址,因此,对数组指针p有另一种赋值方式:p=a;其意义与p=&a0;相同。 即然数组指针p中的值为a0的地址,

10、那么,*p即代表数组元素a0。如果有*p=5,则a0=5。 可是用数组指针p如何引用数组a中其它元素的值呢?一个概念:一个概念:在C中,指针类型的变量可以进行加减法,如可以有p=p+1,p=p+i,p+等;但是,指针指针变量进行的不是一般的加减法!变量进行的不是一般的加减法!如:若指针变量p中的值为2000,则执行p=p+1后,p中的值并不一定是2001。相加后的值是多少要根据指针p所指向的数据类型来确定。如:若定义int * p;即p指向整型,则执行p=p+1后,p中的值为2002;若定义float * p;则执行p=p+1后,p的值为2004;结论:结论:p=p+1p=p+1的操作是使指针

11、的操作是使指针p p指向数组中的下一指向数组中的下一个元素。个元素。例 p指向float数,则 p+1 p+1 4例 p指向int型数组,且p=&a0; 则p+1 指向a1例 int a10; int *p=&a2; p+; *p=1;例 int a10; int *p1=&a2; int *p2=&a5; 则:p2-p1=3;a0a1a2a3a4a5a6a7a8a9a数组pp+1,a+1p+i,a+ip+9,a+91例:用数组指针输出数组a中的元素mainmain()() int a10=1 int a10=1,3 3,2 2,5 5,4 4,7 7,9 9,

12、8 8,10;10; int int * * p p; forfor(p=ap=a;p &a10p &a10;p+)p+) printf printf(“%d”%d”,* *p p);); 数组元素表示方法a0a1a2a3a9.aa+9a+1a+2地址元素下标法a0a1a2a9a0a1a2a3a9.pp+9p+1p+2地址元素指针法*p*(p+1)*(p+2)*(p+9) 变址运算符ai *(a+i)ai pi *(p+i) *(a+i)*a*(a+1)*(a+2)*(a+9)p0p1p2p9a0a1a2a3a4例 数组元素的引用方法main() int a5,*pa,i; f

13、or(i=0;i5;i+) ai=i+1; pa=a; for(i=0;i5;i+) printf(*(pa+%d):%dn,i,*(pa+i); for(i=0;i5;i+) printf(*(a+%d):%dn,i,*(a+i); for(i=0;i5;i+) printf(pa%d:%dn,i,pai); for(i=0;i5;i+) printf(a%d:%dn,i,ai);12345pamain() int i,*p,a7; p=a; for(i=0;i7;i+) scanf(%d,p+); printf(n); for(i=0;i7;i+,p+) printf(%d,*p);例 注

14、意指针的当前值p=a;pp58762730123456apppppp指针变量可以指到数组后的内存单元数组名作函数参数v数组名作函数参数,是地址传递在C语言中,对于数组名,处理为数组的起始地址,因此,当用数组名作为函数参数时,传递的实际上是地址。或者说,传递的实际上是指针。例:用数组形式和指针形式分别编写strlen函数int strlen(char str ) int i; for(i=0;stri!=0;i+) ; return i; int strlen(char * str ) int i; for( ;*str!=0;str+) i+ ; return i; 指针与二维数组用指针指向多

15、维数组时,在概念和使用上比指向一维数组的指针要复杂一些。先看下面的例子:main()() int i,j,a34; for(i=0;i3;i+) for(j=0;j4;j+) aij=15; printf(“%dn”,a0);); printf(“%dn”,*a);); - 13- 13为什么会这样?因为在二维数组a34中,并不存在a0这个元素,而我们使用了a0,系统对它如何看待呢?如下图所示:l对二维数组 int a34,有ua-二维数组的首地址,即第0行的首地址u对于对于一维数组a10,*a代表第0个元素的值;而对于二维数组a34,*a不是第0个元素的值,而是第0行元素的起始地址u*(ai

16、+j) *(*(a+i)+j) aij第i行第j列的元素地址int a34;a0a1a2200020082016200020022008201020162018a00a01a10a11a20a21a02a03a12a13a22a23aa+1a+2例:输出二维数组中的全部元素。例:输出二维数组中的全部元素。 main()int a34=1,3,5,7,9,; int i,j; for(i=0;i3;i+) for(j=0;j4;j+) printf(“%4d”,aij); printf(“n”); 若改成数组名的指针形式,应如何修改?若改成数组名的指针形式,应如何修改? 用数组名的指针形式用数组

17、名的指针形式输出二维数组中的元素。输出二维数组中的元素。 main()int a34=1,3,5,7,9,; int i,j; for(i=0;i3;i+) for(j=0;j4;j+) printf(“%4d”, *(*(a+i)+j) ); printf(“n”); 关键关键: :当用数组名的指针形式引用当用数组名的指针形式引用二维数组中的元素时二维数组中的元素时, ,是两个是两个 * * 号而非号而非1 1个个 指针与字符串最容易接受的字符串指针应该是下面这种:main() static char a20=“how do you do?”; char * p; int i; p=&

18、;a0; for(i=0;i10;i+) printf(“%c”,*p+);v用字符指针实现但这里要讲的字符串指针是另外一种。看但这里要讲的字符串指针是另外一种。看下面的例子:下面的例子:1) main()2) char * p;3) p=“How do you do?”;4) printf(“%s”,p);5) 注意: 程序第二、三行!程序的第二行定义了一个字符指针变量p ,第三行的作用是会么呢?是把字符串“How do you do?”赋值给指针p吗?当然不是!在C中,字符串与数组名一样,代表的数组的起始地址(应该说,在编译时被转换成地址)。因此,该句的作用是将字符串“How do you

19、 do?”的起始地址赋值给p,也就是说,使指针p指向字符串“How do you do?”。这种方法与用字符数组处理字符串有何区别?试比较以下两种赋值方式的区别:char a =“good!”;printf(“%s”,a);char * p =“good!”;printf(“%s”,p);ag2000ood!0p2000g2000ood!0对于以上两种字符串的处理方式,其结果虽然一样,但其实现机制却大不相同:前者是通过数组来实现,后者则是通过指针实现。我们知道:数组名代表的是数组的起始地址,它是一个常量;而后者则是一个指针变量。因此,我们对于指针变量p,可以写出如下语句:char * p=“a

20、bcde”; printf(“%sn”,p); p=“123456789”; printf(“%sn”,p);对于字符数组a,则不能如此方便地改变其中的值。如果在程序的运行过程中要改变值,只能通过函数调用来实现!例:用指针将字串1的内容复制到字串2。main()() char a=“C program.”; char b20,*p1,*p2; int i; p1=a; p2=b; for( ;* p1!=0;p1+,p2+) * p2 = * p1; * p2=0; printf(“string a is:%sn”,a); printf(“string b is:%sn”,b); 指针数组和指

21、向指针的指针用于处理二维数组或多个字符串指针数组v定义:数组中的元素为指针变量v定义形式:存储类型 数据类型 *数组名元素个数元素个数;char * pa5;/*定义一个有5个元素的一维指针数组;其中的每个元素都是一个字符指针。*/因为每个字符指针同时有是一个字符串指针,可以指向一个字符串;因此,一个指针数组中的多个指针元素可以指向多个字符串。如果有定义: char * pa5=“111”,“2222”, “33333”,“44”,“555”则相当于有: pa0=“111”; pa1=“2222”; pa2=“33333”; pa3=“44”; pa4=“555”;main() int b23

22、,*pb2; int i,j; for(i=0;i2;i+) for(j=0;j3;j+) bij=(i+1)*(j+1); pb0=b0; pb1=b1; for(i=0;i2;i+) for(j=0;j3;j+,pbi+) printf(b%d%d:%2dn,i,j,*pbi);例 用指针数组处理二维数组int *pb2pb0pb1int b23b00 *pb0b01 *(pb0+1)b02 *(pb0+2)b10 *pb1b11 *(pb1+1)b12 *(pb1+2)123246例 对字符串排序(简单选择排序)main() void sort(char *name,int n), pr

23、int(char *name,int n); char *name=Follow me,BASIC, Great Wall,FORTRAN,Computer ; int n=5; sort(name,n); print(name,n);void sort(char *name,int n) char *temp; int i,j,k; for(i=0;in-1;i+) k=i; for(j=i+1;j0) k=j; if(k!=i) temp=namei; namei=namek; namek=temp; name0name1name2name3name4nameGreat WallFORTR

24、ANComputerFollow meBASICkjkjjji=0例 对字符串排序(简单选择排序)main() void sort(char *name,int n), print(char *name,int n); char *name=Follow me,BASIC, Great Wall,FORTRAN,Computer ; int n=5; sort(name,n); print(name,n);void sort(char *name,int n) char *temp; int i,j,k; for(i=0;in-1;i+) k=i; for(j=i+1;j0) k=j; if(

25、k!=i) temp=namei; namei=namek; namek=temp; name0name1name2name3name4nameGreat WallFORTRANComputerFollow meBASICkkjjji=1k例 对字符串排序(简单选择排序)main() void sort(char *name,int n), print(char *name,int n); char *name=Follow me,BASIC, Great Wall,FORTRAN,Computer ; int n=5; sort(name,n); print(name,n);void sor

26、t(char *name,int n) char *temp; int i,j,k; for(i=0;in-1;i+) k=i; for(j=i+1;j0) k=j; if(k!=i) temp=namei; namei=namek; namek=temp; name0name1name2name3name4nameGreat WallFORTRANComputerFollow meBASICkkjji=2例 对字符串排序(简单选择排序)main() void sort(char *name,int n), print(char *name,int n); char *name=Follow

27、me,BASIC, Great Wall,FORTRAN,Computer ; int n=5; sort(name,n); print(name,n);void sort(char *name,int n) char *temp; int i,j,k; for(i=0;in-1;i+) k=i; for(j=i+1;j0) k=j; if(k!=i) temp=namei; namei=namek; namek=temp; name0name1name2name3name4nameGreat WallFORTRANComputerFollow meBASICkkji=3例 对字符串排序(简单

28、选择排序)main() void sort(char *name,int n), print(char *name,int n); char *name=Follow me,BASIC, Great Wall,FORTRAN,Computer ; int n=5; sort(name,n); print(name,n);void sort(char *name,int n) char *temp; int i,j,k; for(i=0;in-1;i+) k=i; for(j=i+1;j0) k=j; if(k!=i) temp=namei; namei=namek; namek=temp; n

29、ame0name1name2name3name4nameGreat WallFORTRANComputerFollow meBASIC命令行参数v命令行:在操作系统状态下,为执行某个程序而键入的一行字符v命令行一般形式:命令名 参数1 参数2参数nmain(int argc, char *argv) v命令行参数传递v带参数的main函数形式:C:TC copy.exe source.c temp.c命令行中参数个数元素指向命令行参数中各字符串首地址形参名任意命令行实参main(形参)系统自动调用main函数时传递第一个参数: main所在的可执行文件名可执行文件名例 输出命令行参数/*tes

30、t.c*/main(int argc, char *argv) while(argc1) +argv; printf(%sn,*argv); -argc; main(int argc, char *argv) while(argc-0) printf(%sn,*argv+);1. 编译、链接test.c,生成可执行文件test.exe2. 在DOS状态下运行(test.exe所在路径下)例如: C:TC test.exe hello world!运行结果:hello world!运行结果:test hello world!argv0argv1argv2char *argvworldtesthelloargvargc=3指向指针的指针l定义形式:存储类型 数据类型 *指针名;如 int *pp;对于指向指针的指针对于指向指针的指针pp,因为它指向的变量是一个指,因为它指向的变量是一个指针变量,即针变量,即(*pp)为指针变量

温馨提示

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

评论

0/150

提交评论