Presentation is loading. Please wait.

Presentation is loading. Please wait.

第九章 指针 西安工程大学.

Similar presentations


Presentation on theme: "第九章 指针 西安工程大学."— Presentation transcript:

1 第九章 指针 西安工程大学

2 本章内容: 9.1 指针的概念 9.2 指针变量 9.3 指针和数组 9.4 指针与字符串 9.5 指针与函数 9.6 返回指针值的函数
9.7 指针数组和指向指针的指针

3 9.1 指针的概念 i k 定义变量: int i; float k; 变量是对程序中数据 存储空间的抽象
内存中每个字节有一个编号-----地址 …... 2000 2001 2002 2005 内存 2003 定义变量: int i; float k; i 编译或函数调用时为其分配内存单元 k 变量是对程序中数据 存储空间的抽象

4 指针:变量的地址 指针变量:存放变量地址的变量 10 变量的内容 变量的地址 指针变量 i_pointer 变量i的地址(指针) 指向
…... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 变量的内容 变量的地址 2000 指针变量 指针变量 i_pointer 变量i 变量i的地址(指针) 变量i的值 指向 地址存入

5 &与*运算符 含义 两者关系:互为逆运算 理解 10 i_pointer = &i = &(*i_pointer)
含义: 取变量的地址 单目运算符 优先级: 2 结合性:自右向左 含义: 取指针所指向变量的内容 单目运算符 优先级: 2 结合性:自右向左 两者关系:互为逆运算 理解 …... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 指针变量 i_pointer = &i = &(*i_pointer) i = *i_pointer = *(&i) i_pointer-----指针变量,它的内容是地址量 *i_pointer----指针的目标变量,它的内容是数据 &i_pointer---指针变量占用内存的地址

6 间接访问:通过存放变量地址的变量去访问变量
直接访问:直接利用变量地址存取变量值 间接访问:通过存放变量地址的变量去访问变量 指针变量 …... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 例 i=3; 直接访问 20 3 例 *i_pointer=20; 间接访问

7 10 例 k=i; --直接访问 k=*i_pointer; --间接访问 10 …... 整型变量i 2000 2001 整型变量k
指针变量 …... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 整型变量k 10

8 9.2 指针变量 9.2.1指针变量的定义 1 指针变量与其所指向的变量之间的关系 2 指针变量的定义形式:
3 变量i &i i_pointer *i_pointer i i=3; *i_pointer=3 2 指针变量的定义形式: [存储类型] 数据类型 *指针名; 例 int *p1,*p2; float *q ; static char *name; 表示定义指针变量 不是‘*’运算符 合法标识符 指针变量本身的存储类型 指针的目标变量的数据类型 注意: 1、int *p1, *p2; 与 int *p1, p2; 2、指针变量名是p1,p2 ,不是*p1,*p2 3、指针变量只能指向定义时所规定类型的变量 4、指针变量定义后,变量值不确定,应用前必须先赋值

9 [存储类型] 数据类型 *指针名=初始地址值;
3 指针变量的初始化形式 [存储类型] 数据类型 *指针名=初始地址值; 例 int i; int *p=&i; 变量必须已说明过 而且类型一致 例 int i; int *p=&i; int *q=p; 例 int *p=&i; int i; 用已初始化指针变量作初值 例 main( ) { int i; static int *p=&i; } () 不能用auto变量的地址 去初始化static型指针

10 注意:指针变量必须先赋值,再使用 改正: 例 main( ) { int i=10; int *p; *p=i;
printf(“%d”,*p); } …... 2000 2004 2006 2005 整型变量i 10 指针变量p 2001 2002 2003 随机 改正: 例 main( ) { int i=10,k; int *p; p=&k; *p=i; printf(“%d”,*p); }

11 9.2.2 指针变量的引用 例9.1 指针变量的引用举例 main() { int a; int *pa=&a; a=10; 10
…... f86 f8a f8c f8b 整型变量a 10 指针变量pa f87 f88 f89 main() { int a; int *pa=&a; a=10; printf("a:%d\n",a); printf("*pa:%d\n",*pa); printf("&a:%x(hex)\n",&a); printf("pa:%x(hex)\n",pa); printf("&pa:%x(hex)\n",&pa); } 运行结果: a:10 *pa:10 &a:f86(hex) pa:f86(hex) &pa:f88(hex)

12 例9.2 输入两个整数,并按从大到小的顺序输出 main() { int *p1,*p2,*p,a,b;
scanf("%d,%d",&a,&b); p1=&a; p2=&b; if(a<b) { p=p1; p1=p2; p2=p;} printf("a=%d,b=%d\n",a,b); printf("max=%d,min=%d\n",*p1,*p2); } …... 指针变量p1 指针变量p 2000 2008 2002 2004 2006 指针变量p2 整型变量b 整型变量a 2006 2008 2006 2008 2006 5 9 运行结果:a=5,b=9 max=9,min=5

13 运行结果:5, 9 9.2.3指针变量作为函数参数 特点:共享内存,“双向”传递——地址传递 例9.3 输入两个整数,并按从大到小的顺序输出
…... 2000 2008 200A 2002 2004 2006 变量a 变量b (main) swap(int x,int y) { int temp; temp=x; x=y; y=temp; } main() { int a,b; scanf("%d,%d",&a,&b); if(a<b) swap(a,b); printf("\n%d,%d\n",a,b); 5 5 9 9 变量temp 变量y 变量x (swap) COPY 值传递 9 5 5 运行结果:5, 9

14 例9.4 输入两个整数,并按从大到小的顺序输出 运行结果:9,5 swap(int *p1, int *p2) { int p; 5 9
…... 2000 2008 200A 2002 2004 2006 200C 200E 2010 ... 整型变量a 整型变量b (main) 指针q1 指针q2 swap(int *p1, int *p2) { int p; p=*p1; *p1=*p2; *p2=p; } main() { int a,b; int *q1,*q2; scanf("%d,%d",&a,&b); q1=&a; q2=&b; if(a<b)swap(q1,q2); printf("\n%d,%d\n",a,b); 5 9 9 5 2000 地址传递 2000 2002 2002 COPY (swap) 指针p1 指针p2 整型p 5 运行结果:9,5

15 例9.5 输入两个整数,并按从大到小的顺序输出 swap(int x,int y) { int t; 5 t=x; x=y; y=t; }
…... 2000 2008 200A 2002 2004 2006 200C 200E 2010 ... 整型a 整型b (main) pointer_1 pointer_2 swap(int x,int y) { int t; t=x; x=y; y=t; } main() { int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a<b) swap(*pointer_1,*pointer_2); printf("\n%d,%d\n",a,b); 5 值传递 9 2000 5 2002 9 COPY (swap) 整型x 整型b 整型t 9 5 5 运行结果:5,9

16 例9.6 输入两个整数,并按从大到小的顺序输出 swap(int *p1, int *p2) { int *p; 5 p=p1;
…... 2000 2008 200A 2002 2004 2006 200C 200E 2010 ... 整型a 整型b (main) pointer_1 pointer_2 swap(int *p1, int *p2) { int *p; p=p1; p1=p2; p2=p; } main() { int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a<b) swap(pointer_1,pointer_2); printf("%d,%d",*pointer_1,*pointer_2); 5 9 2000 2000 2002 2002 COPY (swap) 指针p1 指针p2 指针p **** 2002 2000 2000 运行结果:5,9

17 9.3 指针与数组 9.3.1指向数组元素的指针变量 数组名是表示数组首地址的地址常量 例 int array[10]; int *p;
p=&array[0]; // p=array; 或 int *p=&array[0]; 或 int *p=array; array[0] array[1] array[2] array[3] array[9] ... 整型指针p &array[0] p 数组名是表示数组首地址的地址常量

18 9.3.2 指针的运算 如 int i, *p; p=1000; () i=p; () 1.指针变量的赋值运算
p=&a; (将变量a地址p) p=array; (将数组array首地址p) p=&array[i]; (将数组元素地址p) p1=p2; (指针变量p2值p1) 不能把一个整数p,也不能把p的值整型变量 如 int i, *p; p=1000; () i=p; ()

19 2 指针的算术运算 1 pi  p id (i为整型数,d为p指向的变量所占字节数)
p++, p--, p+i, p-i, p+=i, p-=i等 若p1与p2指向同一数组,p1-p2=两指针间元素个数(p1-p2)/d p1+p2 无意义 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] a数组 p p+1,a+1 p+i,a+i p+9,a+9 例 p指向float数,则 p+1  p+1 4 例 p指向int型数组,且p=&a[0]; 则p+1 指向a[1] 1 例 int a[10]; int *p=&a[2]; p++; *p=1; 例 int a[10]; int *p1=&a[2]; int *p2=&a[5]; 则:p2-p1=3;

20 3 指针变量的关系运算 若p1和p2指向同一数组,则 p1<p2 表示p1指的元素在前 p1>p2 表示p1指的元素在后
p==NULL或p!=NULL

21 a[i]  p[i]  *(p+i) *(a+i)
[] 变址运算符 a[i]  *(a+i) 9.3.3 数组元素引用方法 a[0] a[1] a[2] a[3] a[9] ... a a+9 a+1 a+2 地址 元素 下标法 a[0] a[1] a[2] a[3] a[9] ... p p+9 p+1 p+2 地址 元素 指针法 *p *(p+1) *(p+2) *(p+9) *a *(a+1) *(a+2) *(a+9) p[0] p[1] p[2] p[9] a[i]  p[i]  *(p+i) *(a+i)

22 例9.7 数组元素的引用方法举例 main() { int a[5],*pa,i; for(i=0;i<5;i++) a[i]=i+1; pa=a; printf("*(pa+%d):%d\n",i,*(pa+i)); printf("*(a+%d):%d\n",i,*(a+i)); printf("pa[%d]:%d\n",i,pa[i]); printf("a[%d]:%d\n",i,a[i]); } a[0] a[1] a[2] a[3] a[4] pa 1 2 3 4 5

23 例9.8 int a[]={1,2,3,4,5,6,7,8,9,10},*p=a,i; 数组元素地址的正确表示: (A)&(a+1) (B)a (C)&p (D)&p[i] 数组名是地址常量 p++,p-- () a++,a-- () a+1, *(a+2) ()

24 for(i=0;i<7;i++,p++) printf("%d",*p); }
例9 通过指针变量输出数组中的元素 main() { int i,*p,a[7]; p=a; for(i=0;i<7;i++) scanf("%d",p++); printf("\n"); for(i=0;i<7;i++,p++) printf("%d",*p); } 5 8 7 6 2 3 1 4 a p p p p p p=a; p p p 指针变量可以指到数组后的内存单元, 在此例中需要注意指针的当前值

25 9.3.4 数组名作函数参数 数组名作函数参数,是地址传递 数组名作函数参数,实参与形参的对应关系 实参 形参 数组名 指针变量

26 例9.9.1 将数组a中的n个整数按相反顺序存放 void inv(int x[], int n)
{ int t,i,j,m=(n-1)/2; for(i=0;i<=m;i++) { j=n-1-i; t=x[i]; x[i]=x[j]; x[j]=t; } main() { int i,a[10]={3,7,9,11,0,6,7,5,4,2}; inv(a,10); printf("The array has been reverted:\n"); for(i=0;i<10;i++) printf("%d,",a[i]); printf("\n"); m=4 i j i j i j i j j i 2 3 4 7 5 9 11 7 6 本例中实参与形参 均用数组

27 例9.9.2 将数组a中的n个整数按相反顺序存放 void inv(int *x, int n)
3 7 9 11 6 5 4 2 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] x p=x+m a数组 j i void inv(int *x, int n) { int t,*p,*i,*j,m=(n-1)/2; i=x; j=x+n-1; p=x+m; for(;i<=p;i++,j--) { t=*i; *i=*j; *j=t; } } main() { int i,a[10]={3,7,9,11,0,6,7,5,4,2}; inv(a,10); printf("The array has been reverted:\n"); for(i=0;i<10;i++) printf("%d,",a[i]); printf("\n"); } 2 3 i j 4 7 i j 5 9 i j 7 11 j i 6 实参用数组,形参用指针变量

28 例9.9.3 将数组a中的n个整数按相反顺序存放 void inv(int *x, int n)
{ int t,*i,*j,*p,m=(n-1)/2; i=x; j=x+n-1; p=x+m; for(;i<=p;i++,j--) { t=*i; *i=*j; *j=t; } } main() { int i,a[10],*p=a; for(i=0;i<10;i++,p++) scanf("%d",p); p=a; inv(p,10); printf("The array has been reverted:\n"); for(p=a;p<a+10;p++) printf("%d",*p); } 实参与形参均用指针变量

29 例9.9.4 将数组a中的n个整数按相反顺序存放 void inv(int x[], int n)
{ int t,i,j,m=(n-1)/2; for(i=0;i<=m;i++) { j=n-1-i; t=x[i]; x[i]=x[j]; x[j]=t; } main() { int i,a[10],*p=a; for(i=0;i<10;i++,p++) scanf("%d",p); p=a; inv(p,10); printf("The array has been reverted:\n"); for(p=arr;p<arr+10;p++) printf("%d ",*p); } 实参用指针变量,形参用数组

30 9.3.4 指针与二维数组 对于一维数组: (1)数组名array表示数组的首地址,即array[0]的地址;
int array[10]; array 对于一维数组: (1)数组名array表示数组的首地址,即array[0]的地址; (2)数组名array是地址常量 (3)array+i是元素array[i]的地址 (4)array[i]  *(array+i)

31 1 二维数组的地址 int a[3][4]; a a+1 a+2 *(a[0]+1) *(*(a+0)+1) 2000 2000 a[0]
2008 2016 a a+1 a+2 2000 2002 2008 2010 2016 2018 a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] a[0][2] a[0][3] a[1][2] a[1][3] a[2][2] a[2][3] a[0]+1 a[1]+1 a[2]+1 *(a+0)+1 *(a+1)+1 *(a+2)+1 对于二维数组: (1)a是数组名, 包含三个元素 a[0],a[1],a[2] (2)每个元素a[i] 又是一个一维 数组,包含4个 元素

32 int a[3][4]; a a+1 a+2 对二维数组 int a[3][4],有 a-----二维数组的首地址,即第0行的首地址
2000 2008 2016 2002 2010 2018 a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] a[0][2] a[0][3] a[1][2] a[1][3] a[2][2] a[2][3] a a+1 a+2 对二维数组 int a[3][4],有 a-----二维数组的首地址,即第0行的首地址 a+i-----第i行的首地址 a[i]  *(a+i)------第i行第0列的元素地址 a[i]+j  *(a+i)+j -----第i行第j列的元素地址 *(a[i]+j)  *(*(a+i)+j)  a[i][j] a+i=&a[i]=a[i]=*(a+i) =&a[i][0], 值相等,含义不同 a+i  &a[i],表示第i行首地址,指向行 a[i]  *(a+i)  &a[i][0],表示第i行第0列元素地址,指向列

33 int a[3][4]; 地址表示: (1) a+1 (2) &a[1][0] (3) a[1] (4) *(a+1)
行指针 列指针 地址表示: (1) &a[1][2] (2) a[1]+2 (3) *(a+1)+2 (4)&a[0][0]+1*4+2 二维数组元素表示形式: (1)a[1][2] (2)*(a[1]+2) (3)*(*(a+1)+2) (4)*(&a[0][0]+1*4+2)

34 *(a[1]+2),*(*(a+1)+2),a[1][2]
表示形式 含义 地址 a 二维数组名,数组首地址 a[0],*(a+0),*a 第0行第0列元素地址 a+1 第1行首地址 a[1],*(a+1) 第1行第0列元素地址 a[1]+2,*(a+1)+2,&a[1][2] 第1行第2列元素地址 *(a[1]+2),*(*(a+1)+2),a[1][2] 第1行第2列元素值 2000 2008 2012 13

35 p 例9.10 用指针变量输出数组元素的值 main()
int a[3][4]; a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] a[0][2] a[0][3] a[1][2] a[1][3] a[2][2] a[2][3] p 例9.10 用指针变量输出数组元素的值 main() { static int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int *p; for(p=a[0];p<a[0]+12;p++) { if((p-a[0])%4==0) printf("\n"); printf("%4d ",*p); }

36 例9.11 二维数组与指针运算 main() { int a[3][4]={{1,2,3,4},{3,4,5,6},{5,6,7,8}};
int i; int (*p)[4]=a,*q=a[0]; for(i=0;i<3;i++) { if(i==0) (*p)[i+i/2]=*q+1; else p++,++q; } printf("%d,",a[i][i]); printf("%d,%d\n",*((int *)p),*q); p q p q p q 1 2 3 4 5 6 7 8 2 运行结果: 2,4,7,5,3

37 若int a[3][4]; int (*p1)[4]=a; int *p2=a[0];
2 二维数组的指针作为函数参数 实参 形参 数组名int x[][4] 指针变量int (*q)[4] 指针变量int (*q)[4] 数组名a 指针变量p1 若int a[3][4]; int (*p1)[4]=a; int *p2=a[0]; 指针变量p2 指针变量int *q

38 例9.12 输入3个学生4门课的成绩,计算总平均分,并输出第n个学生成绩
void average(float *p,int n) { float *p_end, sum=0,aver; p_end=p+n-1; for(;p<=p_end;p++) sum=sum+(*p); aver=sum/n; printf("average=%5.2f\n",aver); } void search(float (*p)[4], int n) { int i; printf(" No.%d :\n",n); for(i=0;i<4;i++) printf("%5.2f ",*(*(p+n)+i)); main() { void average(float *p,int n); void search(float (*p)[4],int n); float score[3][4]= {{65,67,79,60},{80,87,90,81}, {90,99,100,98}}; average(*score,12); search(score,2); } 函数说明 p float p[][4] p 65 52 79 60 80 87 90 81 99 100 98 等价于 p[n][i]

39 9.4 指针与字符串 1 字符串的表示形式 例14 用字符数组存放一个字符串并输出 main( )
l o v e C h i string[0] string[1] string[2] string[3] string[4] string[5] string[6] string[7] string[8] string[9] string string[10] string[11] string[12] string[13] n ! a \0 例14 用字符数组存放一个字符串并输出 main( ) { char string[]=“I love China!”; printf(“%s\n”,string); printf(“%s\n”,string+7); }

40 例9.14 用字符指针指向一个字符串 字符指针初始化:把字符串首地址赋给string  char *string;
l o v e C h i string n ! a \0 例9.14 用字符指针指向一个字符串 字符指针初始化:把字符串首地址赋给string  char *string; string=“I love China!”; 例 main( ) { char *string=“I love China!”; printf(“%s\n”,string); string+=7; while(*string) { putchar(string[0]); string++; } string *string!=0

41 2 字符串指针作函数参数 void copy_string(char from[],char to[]) { int i=0;
e c h \0 r . from b y u a r s t n d e to o . \0 I a e c h \0 r . t m 2 字符串指针作函数参数 void copy_string(char from[],char to[]) { int i=0; while(from[i]!='\0') { to[i]=from[i]; i++; } to[i]='\0'; main() { char a[]="I am a teacher."; char b[]="You are a student."; printf("string_a=%s\n string_b=%s\n",a,b); copy_string(a,b); printf("\nstring_a=%s\nstring_b=%s\n",a,b); 例9.15 用函数调用实现字符串复制 void copy_string(char *from,char *to) { for(;*from!='\0';from++,to++) *to=*from; *to='\0'; } main() { char *a="I am a teacher."; char *b="You are a student."; printf("string_a=%s\nstring_b=%s\n",a,b); copy_string(a,b); printf("\nstring_a=%s\nstring_b=%s\n",a,b); (1)用字符数组作参数 (2)用字符指针变量作参数

42 3 字符指针变量与字符数组的讨论 char *cp; 与 char str[20];
str由若干元素组成,每个元素放一个字符;而cp中存放字符串首地址 char str[20]; str=“I love China!”; () char *cp; cp=“I love China!”; () str是地址常量;cp是地址变量 cp接受键入字符串时,必须先开辟存储空间 例 char str[10]; scanf(“%s”,str); () 而 char *cp; scanf(“%s”, cp); () 改为: char *cp,str[10]; cp=str; scanf(“%s”,cp); ()

43 字符串与数组关系 字符串用一维字符数组存放 字符数组具有一维数组的所有特点 数组名是指向数组首地址的地址常量
数组元素的引用方法可用指针法和下标法 数组名作函数参数是地址传递等 区别 存储格式:字符串结束标志 赋值方式与初始化 输入输出方式:%s %c

44 char str[]={“Hello!”}; ()
char *cp=“Hello”; () int a[]={1,2,3,4,5}; () int *p={1,2,3,4,5}; () char str[10],*cp; int a[10],*p; str=“Hello”; () cp=“Hello!”; () a={1,2,3,4,5}; () p={1,2,3,4,5}; () scanf(“%s”,str); printf(“%s”,str); gets(str); puts(str);

45 9.5 指针与函数 9.5.1 指向函数的指针变量 定义形式: 数据类型 (*指针变量名)(); ( )不能省 函数返回值的数据类型
9.5 指针与函数 9.5.1 指向函数的指针变量 定义形式: 数据类型 (*指针变量名)(); 如 int (*p)(); max …... 指令1 指令2 ( )不能省 int (*p)() 与 int *p()不同 函数返回值的数据类型 函数指针变量赋值:如p=max; 专门存放函数入口地址 可指向返回值类型相同的不同函数 函数调用形式: c=max(a,b);  c=(*p)(a,b); 对函数指针变量pn, p++, p--无意义 函数在编译时被分配的入口地址,该入口地址就称为函数的指针 函数指针变量指向的函数必须有函数说明

46 用指针变量调用函数: 一般方法: 例9.16 求a和b两个数中的较大者。 main()
{ int max(int ,int), (*p)( ); int a,b,c; p=max; scanf("%d,%d",&a,&b); c=(*p)(a,b); printf("a=%d,b=%d,max=%d\n",a,b,c); } int max(int x,int y) { int z; if(x>y) z=x; else z=y; return(z); 一般方法: main() { int max(int ,int); int a,b,c; scanf("%d,%d",&a,&b); c=max(a,b); printf("a=%d,b=%d,max=%d\n",a,b,c); } int max(int x,int y) { int z; if(x>y) z=x; else z=y; return(z); 例9.16 求a和b两个数中的较大者。

47 9.5.2 用函数指针变量作函数参数 例9.17 用函数指针变量作参数,求最大值、最小值和两数之和 void main()
例9.17 用函数指针变量作参数,求最大值、最小值和两数之和 void main() { int a,b,max(int,int), min(int,int),add(int,int); void process(int,int,int (*fun)()); scanf("%d,%d",&a,&b); process(a,b,max); process(a,b,min); process(a,b,add); } void process(int x,int y,int (*fun)()) { int result; result=(*fun)(x,y); printf("%d\n",result); max(int x,int y) { printf(“max=”); return(x>y?x:y); min(int x,int y) { printf(“min=”); return(x<y?x:y); add(int x,int y) { printf(“sum=”); return(x+y);

48 9.6 返回指针值的函数 函数定义形式: main() { float score[][4]={{60,70,80,90},
{56,89,67,88},{34,78,90,66}}; float *search(float (*pointer)[4],int n), *p; int i,m; printf("Enter the number of student:"); scanf("%d",&m); printf("The scores of No.%d are:\n",m); p=search(score,m); for(i=0;i<4;i++) printf("%5.2f\t",*(p+i)); } float *search(float (*pointer)[4], int n) { float *pt; pt=*(pointer+n); return(pt); 9.6 返回指针值的函数 函数定义形式: 类型标识符 *函数名(参数表); 例 int *f(int x, int y) 例9.18 指针函数实现:有若干学生成绩,要求输入学生序号后,能输出其全部成绩 p p p p pointer pointer+1 34 78 90 66 56 89 67 88 60 70 80 score数组

49 例9.19.1 写一个函数,求两个int型变量中居于较大值的变量的地址
…... 2000 2008 200A 2002 2004 2006 int *f1(int *x,int *y) { if(*x>*y) return x; else return y; } main() { int a=2,b=3; int *p; p=f1(&a, &b); printf("%d\n",*p); 变量a 变量b (main) 指针变量p COPY 2 3 2002 ** 指针变量y 指针变量x (f1) 2000 2002

50 例9.19.2 写一个函数,求两个int型变量中居于较大值的变量的地址
…... 2000 2008 200A 2002 2004 2006 int *f3(int x,int y) { if(x>y) return &x; else return &y; } main() { int a=2,b=3; int *p; p=f3(a, b); printf("%d\n",*p); 变量a 变量b (main) 指针变量p COPY 2 3 200A ** 变量y 变量x (f3) 2 3

51 9.7 指针数组和多级指针 9.7.1 指针数组 定义:数组中的元素为指针类型的数据.
定义形式:[存储类型] 数据类型 *数组名[数组长度]; 例 int *p[4]; 指针数组赋值与初始化 指针本身的存储类型 指针所指向变量的数据类型 区分int *p[4]与int (*p)[4] 初始化: main() { int b[2][3],*pb[ ]={b[0],b[1]}; …….. } int *pb[2] pb[0] pb[1] int b[2][3] 1 2 3 4 6 赋值: main() { int b[2][3],*pb[2]; pb[0]=b[0]; pb[1]=b[1]; …….. } int *pb[2] pb[0] pb[1] int b[2][3] 1 2 3 4 6

52 p[0]=a; p[1]=b; p[2]=c; p[3]=NULL; …….. } 或: { char *p[4];
指针数组赋值与初始化举例 L i s p \0 F o r t r a n \0 B a s i c \0 p[0] p[1] p[2] p[3] 赋值: main() { char a[]="Fortran"; char b[]="Lisp"; char c[]="Basic"; char *p[4]; p[0]=a; p[1]=b; p[2]=c; p[3]=NULL; …….. } 或: { char *p[4]; p[0]= "Fortran"; p[1]= "Lisp"; p[2]= "Basic"; p[3]=NULL; 初始化: main() { char *p[]={"Fortran", "Lisp", "Basic",NULL}; …….. } L i s p \0 F o r t r a n \0 B a s i c \0 p[0] p[1] p[2] p[3]

53 二维数组与指针数组区别: 指针数组元素的作用相当于二维数组的行名 二维数组存储空间固定 但指针数组中元素是指针变量
char name[5][9]={“gain”,“much”,“stronger”, “point”,“bye”}; g a i n \0 s t r o n g e r \0 p o i n t \0 m u c h \0 b y e \0 g a i n \0 s t r o n g e r \0 p o i n t \0 m u c h \0 name[0] name[1] name[2] name[3] name[4] b y e \0 char *name[5]={“gain”,“much”,“stronger”, “point”,“bye”}; 二维数组存储空间固定 字符指针数组相当于可变列长的二维数组 分配内存单元=数组元素个数*2+各字符串长度 指针数组元素的作用相当于二维数组的行名 但指针数组中元素是指针变量 二维数组的行名是地址常量

54 例9.20 将若干字符串按字母顺序由小到大输出 k k j j j j i=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;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0) k=j; if(k!=i) { temp=name[i]; name[i]=name[k]; name[k]=temp;} 例9.20 将若干字符串按字母顺序由小到大输出 name k name[0] Follow me k j name[1] BASIC j name[2] Great Wall j name[3] FORTRAN j name[4] Computer i=0

55 k j k j k j i=1 name name[0] Follow me name[1] BASIC name[2]
Great Wall k j name[3] FORTRAN k j name[4] Computer i=1

56 9.7.2 多级指针(指向指针的指针) 一级指针:指针变量中存放目标变量的地址 例 int *p; int i=3; p=&i; *p=5;
单级间接寻址 二级指针:指针变量中存放一级指针变量的地址 例 int **p1; int *p2; int i=3; p2=&i; p1=&p2; **p1=5; p1 &p2 &i 3 P2(指针变量) i(整型变量) 二级指针 一级指针 目标变量 二级间接寻址

57 定义形式:[存储类型] 数据类型 **指针名;
如 char * * p; *p是p间接指向对象的地址 **p是p间接指向对象的值 指针本身的存储类型 最终目标变量的数据类型 i p1 p2 3 &i &p1 例 int i=3; int *p1; int **p2; p1=&i; p2=&p1; **p=5; **p2, *p1 *p2 例 int i, **p; p=&i; ()//p是二级指针,不能用变量地址为其赋值

58 char *name[]={"hello","good","world","bye",""}; p=name+1;
例9.21 用二级指针处理字符串 用*p可输出地址(%o或%x), 也可用它输出字符串(%s) #define NULL 0 void main() { char **p; char *name[]={"hello","good","world","bye",""}; p=name+1; printf("%o : %s ", *p,*p); p+=2; while(**p!=NULL) printf("%s\n",*p++); } name[0] name[1] name[2] name[3] name[4] char *name[5] world bye \0 hello good name p *(p++) p 运行结果: 644 : good bye

59 二级指针与指针数组的关系 int **p 与 int *q[10] 指针数组名是二级指针常量 p=q; p+i 是q[i]的地址
指针数组作形参,int *q[ ]与int **q完全等价;但作为变量定义两者不同 系统只给p分配能保存一个指针值的内存区;而给q分配10块内存区,每块可保存一个指针值

60 C:\TC> copy[.exe] source.c temp.c
9.7.3 指针数组作main函数的形参 Main函数可以有参数 ,例如 实在参数是和命令行一起给出,命令行格式: 命令名 参数1 参数2………参数n 命令行参数传递 main(int argc, char *argv[]) { ……… } C:\TC> copy[.exe] source.c temp.c 形参名任意 命令行中参数个数 元素指向命令行参数 中各字符串首地址 命令行实参 main(形参) 系统自动调用 main函数时传递 有3个字符串参数的命令行 第一个参数: main所在的可执行文件名

61 例9.22 输出命令行参数 main(int argc, char *argv[])
例9.22 输出命令行参数 main(int argc, char *argv[]) { while(argc>1) { ++argv; printf("%s\n",*argv); --argc; } main(int argc, char *argv[]) { while(argc-->0) printf("%s\n",*argv++); } argv[0] argv[1] argv[2] char *argv[] world test hello argv argc=3 运行结果:test hello world! 1. 编译、链接test.c,生成可执行文件test.exe 2. 在DOS状态下运行(test.exe所在路径下) 运行结果:hello world! 例如: C:\TC> test[.exe] hello world!

62 9.8本章小节 指针的数据类型 定义 含义 int i; 定义整型变量i p为指向整型数据的指针变量 int *p; int a[n];
int *p[n]; int (*p)[n]; int f(); int *p(); int (*p)(); int **p; 定义整型变量i p为指向整型数据的指针变量 定义含n个元素的整型数组a n个指向整型数据的指针变量组成的指针数组p p为指向含n个元素的一维整型数组的指针变量 f为返回整型数的函数 p为返回指针的函数,该指针指向一个整型数据 p为指向函数的指针变量,该函数返回整型数 p为指针变量,它指向一个指向整型数据的指针变量 指针的数据类型 9.8本章小节

63 例 下列定义的含义 (1)int *p[3]; (2)int (*p)[3]; (3)int *p(int); (4)int (*p)(int); (5)int *(*p)(int); (6)int (*p[3])(int); (7)int *(*p[3])(int); 指针数组 指向一维数组的指针 返回指针的函数 指向函数的指针,函数返回int型变量 指向函数的指针,函数返回int 型指针 函数指针数组,函数返回int型变量 函数指针数组,函数返回int型指针


Download ppt "第九章 指针 西安工程大学."

Similar presentations


Ads by Google