1 / 108

第十章 指 针

本章内容 : 1. 地址和指针的概念 2. 变量的指针和指向变量的指针变量 3. 数组的指针和指向数组的指针变量 4. 字符串的指针和指向字符串的指针变量 5. 函数的指针和指向函数的指针变量 6. 指针数组和指向指针的指针. 第十章 指 针. 概 述: 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。 利用指针变量 可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。

zandra
Download Presentation

第十章 指 针

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 本章内容: 1.地址和指针的概念 2.变量的指针和指向变量的指针变量 3.数组的指针和指向数组的指针变量 4.字符串的指针和指向字符串的指针变量 5.函数的指针和指向函数的指针变量 6.指针数组和指向指针的指针 第十章 指 针

  2. 概 述: 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。 利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。 指针极大地丰富了C语言的功能。 学习指针是学习C语言中最重要的一环,能否正确理解和使用指针是我们是否掌握C语言的一个标志。同时,指针也是C语言中最为困难的一部分,在学习中除了要正确理解基本概念,还必须要多编程,上机调试。只要作到这些,指针也是不难掌握的。

  3. 10.1 地址和指针的概念 在计算机中,所有的数据都是存放在存储器中的。 一般把存储器中的一个字节称为一个内存单元, 不同的数据类型所占用的内存单元数不等,如整型量占2个单元,字符量占1个单元等, 在第二章中已有详细的介绍。 为了正确地访问这些内存单元, 必须为每个内存单元编上号。 根据一个内存单元的编号即可准确地找到该内存单元。内存单元的编号也叫做地址。 既然根据内存单元的编号或地址就可以找到所需的内存单元,所以通常也把这个地址称为指针。 1、地址:内存单元的编号,通常一个字节(1B)一个编号。 2、指针:内存单元的地址。

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

  5. 3、内存单元的指针和内存单元的内容是两个不同的概念 4、内存数据的访问方式: (1)直接访问——按变量名存取变量 (2)间接访问——将变量的地址存放在另一个变量(指针变量),通过指针变量来访问。 地址 …….. 在C语言中, 允许用一个变量来存放指针,这种变量称为指针变量。一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。 2000 30 变量i 2002 50 变量j 2004 60 变量k 指针变量 ip 2000

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

  7. …... 整型变量i 2000 10 2001 2002 2003 变量i_pointer 2004 2005 变量地址(指针) 指针变量 2006 地址存入 指针变量 指向 …... 变量值 变量 • 指针与指针变量 • 指针:一个变量的地址 • 指针变量:专门存放变量地址的变量叫~ 指针 变量的内容 变量的地址 2000 指针变量

  8. 注意:严格地说,一个指针是一个地址, 是一个常量。而一个指针变量却可以被赋予不同的指针值,是变量。 但经常把指针变量简称为指针。 为了避免混淆,我们中约定: “指针”是指地址, 是常量, “指针变量”是指取值为地址的变量。 定义指针的目的是为了通过指针去访问内存单元。

  9. 10.2 变量的指针和指向变量的指针变量 • 变量的指针——变量的地址 • 例:&a 为变量a在内存单的存放地址,也称变量a的指针 • 指针变量——存放地址的变量 • 指向变量的指针变量——一个指针变量存放变量a的地址,则称 • 该指针变量为指向变量a的指针变量。 pa a 例: int a=10; int *pa pa=&a &a 10

  10. 一、指针变量的定义: 其一般形式为: 类型说明符 *变量名; 其中,*表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型。 例如: int *p1; 表示p1是一个指针变量,它的值是某个整型变量的地址。 或者说p1指向一个整型变量。至于p1究竟指向哪一个整型变量, 应由向p1赋予的地址来决定。

  11. 再如: static int *p2; /*p2是指向静态整型变量的指针变量*/ float *p3; /*p3是指向浮点变量的指针变量*/ char *p4; /*p4是指向字符变量的指针变量*/ 应该注意的是,一个指针变量只能指向同类型的变量, 如: p3 只能指向浮点变量,不能时而指向一个浮点变量, 时而又指向一个字符变量。

  12. 二、指针变量的赋值 指针变量同普通变量一样,使用之前不仅要定义说明,而且必须赋予具体的值。未经赋值的指针变量不能使用, 否则将造成系统混乱,甚至死机。指针变量的赋值只能赋予地址, 决不能赋予任何其它数据,否则将引起错误。 C语言中提供了地址运算符&来表示变量的地址。 其一般形式为:& 变量名; 例如:&a变示变量a的地址,&b表示变量b的地址。 变量本身必须预先说明。设有指向整型变量的指针变量p,如要把整型变量a 的地址赋予p可以有以下两种方式: (1)指针变量初始化的方法: int a; int *p=&a; (2)赋值语句的方法: int a, *p; p=&a;

  13. 例int *p=&i; int i; • 指针变量的初始化 一般形式:[存储类型]数据类型 *指针名=初始地址值; 例 int i; int *p=&i; 赋给指针变量, 不是赋给目标变量 变量必须已说明过 类型应一致 例 int i; int *p=&i; int *q=p; 用已初始化指针变量作初值 例main( ) { int i; static int *p=&i; .............. } () 不能用auto变量的地址 去初始化static型指针

  14. …... 整型变量i 2000 10 2001 2002 2003 指针变量p 2004 2005 随机 2006 …... 指针变量必须先赋值,再使用 例 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); }

  15. 三、指针变量的运算(引用) 指针变量可以进行某些运算,但其运算的种类是有限的。 它只能进行赋值运算和部分算术运算及关系运算。 1.指针运算符 (1)取地址运算符 & 取地址运算符&是单目运算符,其结合性为自右至左,其功能是取变量的地址。例:&a 即变量a的地址 (2)取内容运算符 * 取内容运算符*是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量。在*运算符之后跟的变量必须是指针变量。 例:int a=10 , *pa=&a; *pa a 即为变量a 的值。

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

  17. 注意:指针运算符*和指针变量说明中的指针说明符* 不是一回事。 在指针变量说明中,“*”是类型说明符,表示其后的变量是指针类型。 而表达式中出现的“*”则是一个运算符用以表示指针变量所指的变量。 main() { int a=5,*p=&a; printf ("%d",*p); } 表示指针变量p取得了整型变量a的地址。 本语句表示输出变量a 的值。 等价于: printf("%d",a);

  18. 说明: 若有定义: int a, *p=&a (1) &*p 表示:p (2) *&a 表示:a (3) (*p)++ 相当于 a++ (4) *p++ 相当于 *(p++),即先取p所指向变量的值,然后,让p指向下一个存储单元。 (5) *++p 相当于 *(++p) 即先让p指向下一个存储单元,然后再取p所指向变量的值。 例: int a,b,*pa=&a,*pb=&b; pa=pb; *pa=*pb; 上面两个语句的含意是什么?

  19. 例y7-1.c:利用指针输入变量的值 main() { int a,b; int *p; p=&a; scanf("%d",p); p=&b; scanf("%d",p); printf(”a=%d, b=%d\n", a,b); } 11 12

  20. 2 赋值运算 指针变量的赋值运算有以下几种形式: ①指针变量初始化赋值,前面已作介绍。 ②把一个变量的地址赋予指向相同数据类型的指针变量。 例如: int a,*pa; pa=&a; /*把整型变量a的地址赋予整型指针变量pa*/ ③把一个指针变量的值赋予指向相同类型变量的另一个指针变量。 如: int a,*pa=&a,*pb; pb=pa; 把a的地址赋予指针变量pb, 由于pa,pb均为指向整型变量的指针变量, 因此可以相互赋值 pa a &a 10 pb &a

  21. ④把数组的首地址赋予指向数组的指针变量。 例如: int a[5],*pa; pa=a; (C语言规定数组名表示数组的首地址) 也可写为: pa=&a[0]; 数组第一个元素的地址也是整个数组的首地址,也可赋予pa 当然也可采取初始化赋值的方法: int a[5],*pa=a; ⑤把字符串的首地址赋予指向字符类型的指针变量。 例如: char *pc; pc="C language"; 或用初始化赋值的方法写为: char *pc="C Language"; 这里应说明的是并不是把整个字符串装入指针变量, 而是把存放该字符串的字符数组的首地址装入指针变量。

  22. 说明:指针变量可以赋予0值,则p=0表明p是空指针,它不指向任何变量;在头文件"stdio.h"中有: #define NULL 0,因此在C程序的常常使用 int *p=NULL;让指针变量为空指针。 对指针变量赋0值和不赋值是不同的。指针变量未赋值时,可以是任意值,是不能使用的。否则将造成意外错误。而指针变量赋0值后,则可以使用,只是它不指向具体的变量而已。 例:教材p206 main() { int a,b,*p,*p1=&a,*p2=&b; scanf("%d%d",p1,p2); if(a<b){ p=p1; p1=p2; p2=p;} printf("\na=%d, b=%d\n\n", a,b); printf("max=%d, min=%d\n", *p1,*p2); } [程序演示]

  23. main() { int a,b,*p,*p1=&a,*p2=&b; scanf("%d%d",p1,p2); if(a<b){ p=p1; p1=p2; p2=p;} printf("\na=%d, b=%d\n\n", a,b); printf("max=%d, min=%d\n", *p1,*p2); } p p1 p1 a a &a 5 &a 5 p2 b p2 b &b 9 &b 9

  24. 四、指针变量作为函数参数 在第八章已学过:函数的参数可以是:整型、实型、字符型等数据。C语言中函数的参数还可以是指针类型,其作用是用来传递一个变量的地址。 例10.3 写一交换两个变量值的函数swap() void swap(int *x, int *y) { int temp; temp=*x; *x=*y; *y=temp; } main() { int a,b,*p,*p1=&a,*p2=&b; scanf("%d%d",p1,p2); printf("\na=%d, b=%d\n\n", a,b); swap(p1,p2); printf("\na=%d, b=%d\n\n", a,b); }

  25. p1 p1 a p1 a a p1 a &a 5 &a 5 &a 9 &a 9 p2 b x x p2 b &b 9 &a &a &b 5 调用前 p2 调用结束后 p2 b b &b 9 &b 5 y y &b &b 调用时 在函数swap()中 程序的执行过程

  26. 若将swap函数写为如下: 指针变量在使用前 必须赋值! void swap(int *x, int *y) { int *temp; *temp=*x; *x=*y; *y=*temp; } 此语句不对,因指针temp变量没有明确指向。 若将swap函数写为如下: main() { int a,b; scanf("%d%d",&a,&b); printf("\na=%d, b=%d\n\n", a,b); swap(a,b); printf("\na=%d, b=%d\n\n", a,b); } void swap(int x, int y) { int temp; temp=x; x=y; y=temp; }

  27. a a a 5 a 5 5 5 b x b 5 x 9 9 9 调用前 b 9 b 9 调用结束后 y 9 y 5 调用时 在函数swap()中 程序的执行过程

  28. 10.3 数组的指针和指向数组的指针变量 概念: 一个数组是由连续的一块内存单元组成的。C语言规定:数组名就是这块连续内存单元的首地址(称为数组的指针)。一个数组也是由各个数组元素(下标变量) 组成的。每个数组元素按其类型不同占有几个连续的内存单元。一个数组元素的首地址也是指它所占有的几个内存单元的首地址。 一个指针变量既可以指向一个数组,也可以指向一个数组元素, 可把数组名或第一个元素的地址赋予它。如要使指针变量指向第i号元素可以把i元素的首地址赋予它或把数组名加i 赋予它。

  29. 一、指向数组元素的指针 p,a,&a[0] a[0] 1 p+1,a+1,&a[1] a[1] 例:int a[10]; int *p=a; p,a,&a[0]均指向同一单元,它们是数组a的首地址,也是0号元素a[0]的地址。 3 a[2] 5 a[3] 7 9 p+i,a+i,&a[i] p+1,a+1,&a[1]均指向1号元素a[1]。 a[i] 类推可知p+i,a+i,&a[i]指向i号元素a[i]。 19 a[9] 应该说明的是p是指针变量,而a,&a[i]都是常量。在编程时应予以注意。

  30. 二、通过指针引用数组元素 引入指针变量后,就可以用两种方法来访问数组元素了。 第一种方法为下标法,即用a[i]形式访问数组元素。 第二种方法为指针法,即采用*(a+i)形式,用间接访问的方法来访问数组元素。 main() { int a[5],i,*pa=a; for(i=0;i<5;i++) {scanf("%d”, pa); pa++; } pa=a; for(i=0;i<5;i++) { printf("a[%d]=%d\n",i,*pa); pa++; } } main() { int a[5],i; for(i=0;i<5;i++) scanf("%d”, &a[i]); for(i=0;i<5;i++) printf("a[%d]=%d\n",i,a[i]); }

  31. main() { int a[5],i; for(i=0;i<5;i++) *(a+i)=i; for(i=0;i<5;i++) printf("a[%d]=%d\n",i,*(a+i)); } 三种方式的比较:教材Pg. 213。 (1)下表法比较直观,但执行效率低。 (2)a[i] 编译时转换为*(a+i) ,计算出元素的地址。 (3)使用指针变量,引用元素,因p++指向下一个元素,因执行效率较高。

  32. 使用指针变量要注意的几个问题: 1、指针变量可实现本身值的改变 例如: int a[10],*p=a p++ 指向a[1]元素 可以使用下面语句来输入数组元素。 for(p=a;p<a+10;p++) scanf("%d",p); 因使用指针变量引用数组元素时要注意指针变量当前的指向,否将出错。 2、数组名表示数组的首地址,是个地址常量,不出现如下运算: × × × a++; a=&a[i]; a=p;

  33. 例10.6 通过指针变量输入输出 a数组的10个元素。 p a[0] 1 a[1] 3 a[2] 5 main() { int a[10],i,*p=a; for(i=0;i<10;i++) scanf("%d", p++); printf("\n"); for(i=0;i<10;i++,p++) printf("a[%d]=%d\n",i,*p); } a[3] 7 9 … a[9] p ------ ------ ------ 分析上述程序中存在的问题?

  34. 注意指针变量的运算: 设有定义: int a[10],*p=a; (1) p++ 指向下一个元,p的实际值加sizeof(int) 2, (2) *p++ 等价于 *(p++) (3) *(p++) 与 *(++p)不同 (4) (*p)++ 表示p当前所指向的元素加1 (5) 若:p=&a[i] 则: *(p--) 相当于a[i--] *(--p) 相当于a[--i] *(p++) 相当于a[i++] *(++p) 相当于a[++i] p-a 的值为 i

  35. 例y7-2.c:利用指针实现将5个整数输入到数组a中,然后将a逆序复制到b中,并输出b中各单元的值 例y7-2.c:利用指针实现将5个整数输入到数组a中,然后将a逆序复制到b中,并输出b中各单元的值 main() { int a[5],b[5], i; int *pa, *pb; pa=a; printf("Input the number\n",); for(i=0;i<5;i++) scanf("%d",pa++); for(i=0;i<5;i++) printf("a[%d]=%d",i,a[i]); printf(" \n"); pa=a; pb=b+4; for(i=0;i<5;i++) *pb--=*pa++; for(i=0;i<5;i++) printf(”b[%d]=%d",i,b[i]); }

  36. 二、数组名和数组指针变量作函数参数 在第八章(函数)中曾经介绍过用数组名作函数的实参和形参的问题。在学习指针变量之后就更容易理解这个问题了。 数组名就是数组的首地址,实参向形参传送数组名实际上就是传送数组的地址, 形参得到该地址后也指向同一数组。 同样,指针变量的值也是地址,数组的指针即为数组的首地址,当然也可作为函数的参数使用。例: float aver(float *pa); main() { float sco[5],av,*sp; int i; sp=sco; printf("\ninput 5 scores:\n"); for(i=0;i<5;i++) scanf("%f",&sco[i]); av=aver(sp); printf("average score is %5.2f",av); } float aver(float *pa) { int i; float av,s=0; for(i=0;i<5;i++) s=s+*pa++; av=s/5; return av; }

  37. 说明:在C语言中形参和实参都可使用指针变量和数组名:说明:在C语言中形参和实参都可使用指针变量和数组名: 1、当形参是数组时,要求对应的实参为: 同类型的数组名或指针变量 2、当形参是指针变量,要求对应的实参为: 同类型的指针变量或数组名 形式参数 指针变量 数组名 实参数 指针变量 数组名 ① ② ③ ④ 例10.7 将数组a中的元素按相反顺序存放。

  38. void inv(int x[],int n) { int t,i,j,m=(n-1)/2; for(i=0;i<=m;i++) j=n-i-1; t=x[i];x[i]=x[j];x[j]=t; } main() { int i,a[10]; for (i=0;i<10;i++) scanf("%d",&a[i]); inv(a,10); for (i=0;i<10;i++) printf("%d ",a[i]); } void inv(int x[],int n) { int t,i,j,m=(n-1)/2; for(i=0;i<=m;i++) j=n-i-1; t=x[i];x[i]=x[j];x[j]=t; } main() { int i,a[10],p=a; for (i=0;i<10;i++) scanf("%d",p++); p=a; inv(p,10); for (i=0;i<10;i++) printf("%d ",p++); }

  39. void inv(int *x,int n) { int t,i,j,m=(n-1)/2; for(i=0;i<=m;i++) j=n-i-1; t=*(x+i); *(x+i)=*(x+j); *(x+j)=t; } main() { int i,a[10]; for (i=0;i<10;i++) scanf("%d",&a[i]); inv(a,10); for (i=0;i<10;i++) print("%d ",a[i]); } void inv(int *x,int n) { int t,i,j,m=(n-1)/2; for(i=0;i<=m;i++) j=n-i-1; t=*(x+i); *(x+i)=*(x+j); *(x+j)=t; } main() { int i,a[10],p=a; for (i=0;i<10;i++) scanf("%d",p++); p=a; inv(p,10); for (i=0;i<10;i++) print("%d ",p++); }

  40. 例p.219 10.8 从10个数中找出最大最小值 void max_min(int a[], int n,int *maxp, int *minp) { int i; *maxp=*minp=a[0]; for(i=0; i<n; i++) { if (a[i]>*maxp ) *maxp=a[i]; if (a[i]<*minp ) *minp=a[i]; } } main() { int i,max,min, number[10]={3,7,9,11,0,6,7,5,4,2}; max_min( ??? ); printf("\nmax=%d, min=%d \n“,max,min); }

  41. void max_min(int a[], int n,int *maxp, int *minp) { int i; *maxp=*minp=a[0]; for(i=0; i<n; i++) { if (a[i]>*maxp ) *maxp=a[i]; if (a[i]<*minp ) *minp=a[i]; } } main() { int i,max1,min1, number1[10]={3,7,9,11,0,6,7,5,4,2}; int max2,min2, number2[20]={3,7,9,11,0,6,7,5,4,2,43,5,34,56,23,41,31,93,23}; max_min(number1,10,max1,min1); printf("\nmax=%d, min=%d \n”,max1,min1); max_min(number2,20,max2,min2 ); printf("\nmax=%d, min=%d \n”, max2,min2); }

  42. 四、指向多维数组的指针变量 (一)、多维数组地址的表示方法 若有定义:int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}}; a[0]+2 数组名a为数组的首地址 2000 a[0] a[0]+1 a[0]+3 2000 a a[0] 0 1 2 3 4 5 6 7 89 10 11 2008 a+1 a[1] 2016 a+2 a[2] 假设数组的首地址为:2000

  43. 二维数组的地址表示: a 二维数组名,数组首地址,0行首地址 a[0],*(a+0),*a,&a[0][0] 第0行第0列元素地址 a+1, &a[1] 第1行首地址 a[1],*(a+1),&a[1][0] 第1行第0列元素地址 a+i, &a[i] 第i行首地址 a[i], *(a+i), &a[i][0] 第i行首地址 #define PF "%d,%d,%d,%d,%d,\n" main() { int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11}; printf(PF,a,*a,a[0],&a[0],&a[0][0]); printf(PF,a+1,*(a+1),a[1],&a[1],&a[1][0]); printf(PF,a+2,*(a+2),a[2],&a[2],&a[2][0]); printf("%d,%d\n",a[1]+1,*(a+1)+1); printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1)); }

  44. 表示形式 地址 含义 a 2000 二维数组名,数组首地址 2000 a[0],*(a+0),*a 第0行第0列元素地址 2008 a+1 第1行首地址 2008 第1行第0列元素地址 a[1],*(a+1) 2012 第1行第2列元素地址 a[1]+2,*(a+1)+2,&a[1][2] 第1行第2列元素值 6 *(a[1]+2),*(*(a+1)+2),a[1][2] #define PF "%d,%d,%d,%d,%d,\n" main() { int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11}; printf(PF,a,*a,a[0],&a[0],&a[0][0]); printf(PF,a+1,*(a+1),a[1],&a[1],&a[1][0]); printf(PF,a+2,*(a+2),a[2],&a[2],&a[2][0]); printf("%d,%d\n",a[1]+1,*(a+1)+1); printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1)); }

  45. 表示形式 地址 含义 a 2000 二维数组名,数组首地址 2000 a[0],*(a+0),*a 第0行第0列元素地址 2008 a+1 第1行首地址 2008 第1行第0列元素地址 a[1],*(a+1) 2012 第1行第2列元素地址 a[1]+2,*(a+1)+2,&a[1][2] 第1行第2列元素值 6 *(a[1]+2),*(*(a+1)+2),a[1][2] 设有定义: int a[3][4],i,j; 引用二维数组元素的方法: (1)下标法: a[i][j] (2)指针法: *(*(a+i)+j)

  46. (二)、多维数组的指针变量 1、指向数组元素的指针变量 设有定义: int a[3][4],i,j; int *p; p=&a[0][0]; p为指向数组元素的指针变量,引用二维数组元素的方法: p+1则表示指向当前元素的下一个元素。 元素a[i][j]的地址表示为: p+4*i+j a[i][j]的值表示为: *(p+4*i+j) 如果一个n*m的二维数组的第i 行j列元素相对于首地址的增量为: i*m+j

  47. 例10.12 用指向数组元素 输出 m main() { int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11}; int i,j,*p; p=&a[0][0]; for(i=0;i<12;i++) {if (i%4==0) printf("\n"); printf("%2d ",*p++); } }

  48. p int a[3][4]; a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[2][0] a[2][1] a[2][2] a[2][3] 例 指向二维数组元素的指针变量 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); } }

  49. 2、指向由m个元素组成的一维数组的指针变量 因为n×m的二维数组a 可分解为一维数组a[0],a[1],.. .a[n-1],而它们分别又是具有m个元素的一维数组。 因此可定义一个指向由m个元素组成的一维数组的指针变量来处理二维数组。把这个指针变量称为:行指针变量 行指针变量说明的一般形式为: 类型说明符 (*指针变量名)[长度] 例: int (*p)[4] 它表示p是一个指针变量,它指向由4个元素组成的一维数组,或说p可指向一个有4列的二维数组。

  50. p a int a[3][4]; p[0]+1或 *p+1 a[0][0] *(*p+1)或 (*p)[1] a[0][1] a[0][2] p+1 a+1 a[0][3] a[1][0] p[1]+2或 *(p+1)+2 a[1][1] *(*(p+1)+2) a[1][2] p+2 a+2 a[1][3] a[2][0] a[2][1] a[2][2] a[2][3] • 指向一维数组的指针变量 • 定义形式: 数据类型 (*指针名)[一维数组维数]; 例 int (*p)[4]; • 可让p指向二维数组某一行 如 int a[3][4], (*p)[4]=a; p的值是一维数组的 首地址,p是行指针 ( )不能少 int (*p)[4]与int *p[4]不同 一维数组指针变量维数和 二维数组列数必须相同

More Related