《c语言电子教案指针》由会员分享,可在线阅读,更多相关《c语言电子教案指针(83页珍藏版)》请在金锄头文库上搜索。
1、UNIX C编程编程yyyy-M- 1age *第第11章章 指指 针针知识点:知识点:&指针的定义指针的定义&指针变量的使用指针变量的使用&各种指针的使用各种指针的使用重点:重点:指针的概念及指针的概念及C语言指针使用的特点语言指针使用的特点指针变量的定义、引用指针变量的定义、引用数组的指针、字符串的指针、函数的指针、指向指针的指针的数组的指针、字符串的指针、函数的指针、指向指针的指针的使用使用难点:难点:s指针的运算和使用指针的运算和使用s指针在数组中的使用及使用特点指针在数组中的使用及使用特点UNIX C编程编程yyyy-M- 2age *q 指针是指针是C语言中的一个重要的概念,也是语
2、言中的一个重要的概念,也是C语言的一个重要语言的一个重要特色。特色。v 可以表示复杂的数据结构可以表示复杂的数据结构v 能动态分配内存能动态分配内存v 能方便地使用字符串能方便地使用字符串v 有效而方便地使用数组有效而方便地使用数组v 在调用函数时能得到多于在调用函数时能得到多于1个的值个的值v 能直接处理内存地址等能直接处理内存地址等第第11章章 指指 针针UNIX C编程编程yyyy-M- 3age * x xxxyz 20002001 20132014 2020202111.1 地址和指针的概念地址和指针的概念q “直接访问直接访问”方式方式 按变量地址存取变量值的方式按变量地址存取变量
3、值的方式int x,y,z;x=20,y=40; z=x+y;x 40x20yz 20002001 20132014 20202021 编译系统把变量名转换为变量的地址,对变量值的存取编译系统把变量名转换为变量的地址,对变量值的存取通过地址进行的。通过地址进行的。 内存内存x 406020yz 20002001 20132014 20202021变量变量z的地址的地址指针指针 UNIX C编程编程yyyy-M- 4age * 11.1 地址和指针的概念地址和指针的概念q “间接访问间接访问”方式方式 通过存放变量地址的变量去访问变量通过存放变量地址的变量去访问变量 int x,*x_point
4、; x_point=&x;*x_point=20;x x_point 20002001 20132014 x 2000x_point 20002001 20132014 x 200020x_point 20002001 20132014 指针指针专门存放变量地址的变量专门存放变量地址的变量指针变量指针变量*x_point指针变量指针变量变量变量变量地址(指针)变量值指向地址存入地址存入指针变量指针变量UNIX C编程编程yyyy-M- 5age *11.1 地址和指针的概念地址和指针的概念整型变量整型变量x指针变量指针变量x_pointer200020042006200520012002200
5、3整型变量整型变量k.102000 k=x; /*直接访问直接访问*/ x_pointer=&x; k=*x_pointer; /*间接访问间接访问*/1010UNIX C编程编程yyyy-M- 6age *q 变量的指针变量的指针v 就是变量的地址就是变量的地址 q 指针变量指针变量v 存放变量地址的变量存放变量地址的变量v 用来指向另一个变量用来指向另一个变量 v 用用“*”符号表示符号表示“指指向向”11.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量UNIX C编程编程yyyy-M- 7age *q定义一个指针变量定义一个指针变量v 指针变量不同于整型变量和其他类型的
6、变量,它是用来专门指针变量不同于整型变量和其他类型的变量,它是用来专门存放地址的。存放地址的。v 必须将指针变量定义为必须将指针变量定义为“指针类型指针类型”。v 一般形式一般形式 基类型基类型 *指针变量名指针变量名; 基类型:指针变量所指向的变量的类型。基类型:指针变量所指向的变量的类型。 例例 float *pointer1; int *pointer2; char *pointer3;v 指针变量的定义是通过指针变量的定义是通过*进行的进行的v 定义后的指针变量只能赋值指针,不能赋值为一般数据类型定义后的指针变量只能赋值指针,不能赋值为一般数据类型11.2 变量的指针和指向变量的指针变
7、量变量的指针和指向变量的指针变量UNIX C编程编程yyyy-M- 8age *q指针变量的引用指针变量的引用v & & 与与* *运算符运算符 - - 单目运算,优先级单目运算,优先级2 2,自右向左结合,自右向左结合 & & 取地址运算符取地址运算符 取变量的地址,取出的地址一定是一个常数取变量的地址,取出的地址一定是一个常数 & &变量名变量名= =指针值指针值 * * 指针运算符指针运算符 指针变量所指向的内存单元,可称为指针变量所指的指针变量所指向的内存单元,可称为指针变量所指的变量变量 与指针变量定义中的与指针变量定义中的* *不同不同 “ “* *指针变量指针变量” ” 可以作为
8、一个基类型变量来用可以作为一个基类型变量来用11.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量UNIX C编程编程yyyy-M- 9age *11.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量main()int a,b; int *pointer_1,*pointer_2; a=100;b=10; pointer_1=&a; /*把变量把变量a的地址赋给的地址赋给pointer_1*/ pointer_2=&b; /*把变量把变量b的地址赋给的地址赋给pointer_2*/ printf(%d,%dn,a,b); printf(%d,%dn,*point
9、er_1,*pointer_2); getch();100,10100,10UNIX C编程编程yyyy-M- 10age *v 指针变量的初始化指针变量的初始化 一般形式一般形式 基类型基类型 *指针变量名指针变量名=初始地址值初始地址值;11.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量例例 int i; int *p=&i;例例 int i; int *p=&i; int *q=p;例例 int *p=&i; int i;用已初始化指针变量作初值用已初始化指针变量作初值ipqipUNIX C编程编程yyyy-M- 11age *11.2 变量的指针和指向变量的指针变量
10、变量的指针和指向变量的指针变量v 指针变量使用前必须先初始化或赋初值指针变量使用前必须先初始化或赋初值例例 main() int i=10, *p; *p=i; printf(“%d”,*p); 指针变量指针变量p整型变量整型变量i2000200420062005200120022003.10200210内容随机内容随机结果:结果:10危险!危险!例例 main( ) int i=10,k, *p; p=&k; *p=i; printf(“%d”,*p); UNIX C编程编程yyyy-M- 12age *v 零指针与空类型指针零指针与空类型指针 零指针:零指针:( (空指针空指针) ) 定义
11、:指针变量值为零定义:指针变量值为零 表示:表示: int * p=0; 11.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量p指向地址为指向地址为0的单元的单元,系统保证该单元不作他用系统保证该单元不作他用(不存放有效数据)(不存放有效数据)表示指针变量值表示指针变量值没有意义没有意义 NULL在在stdio.h中定义,原型为中定义,原型为#define NULL 0 int *p=NULL; 用途用途: 避免指针变量的非法引用避免指针变量的非法引用 在程序中常作为在程序中常作为状态状态比较比较 例例 int *p; . while(p!=NULL) . UNIX C编程编
12、程yyyy-M- 13age *11.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量 空类型指针空类型指针 定义:定义:指针变量不指向哪一种类型数据指针变量不指向哪一种类型数据 表示:表示: void *p; 使用时要进行使用时要进行强制类型转换强制类型转换表示不指定表示不指定p2是指向哪一种是指向哪一种类型数据的指针变量类型数据的指针变量例例 char *p1; void *p2; p1=(char *)p2; p2=(void *)p1;UNIX C编程编程yyyy-M- 14age *11.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量paaffdaf
13、fdeffe0ffdfffdbffdcffdd.ffda10main()int a; int *pa=&a; a=10; printf(a=%d, *pa=%d n,a,*pa); printf(“&a=%x(hex) ,&a); printf(pa=%x(hex) n,pa); printf(&pa=%x(hex)n,&pa); getch();a=10,*pa=10&a=ffda(hex),pa=ffda(hex)&pa=ffde(hex)UNIX C编程编程yyyy-M- 15age * 练习练习11.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量 int x,y,*x
14、_pointer,*y_pointer;x_pointer&xx2y_pointer&yy4 x_pointer=&x;y_pointer=&y;y_pointer=&*x_pointer;y=*&x;2 &与与*运算符右结合运算符右结合 *右侧接指针变量,如:右侧接指针变量,如:*x_pointer &右侧接一般变量,如:右侧接一般变量,如:&xUNIX C编程编程yyyy-M- 16age *q指针变量作为函数参数指针变量作为函数参数 作用是将变量的地址传送到另一个函数中作用是将变量的地址传送到另一个函数中11.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量s *p1,i
15、nt *p2)int temp; temp=*p1; *p1=*p2; *p2=temp;main() int a,b,*pointer_1,*pointer_2; scanf(%d,%d,&a,&b); pointer_1=&a; pointer_2=&b; if(ab) s); printf(n%d,%dn,a,b);pointer_1?a?pointer_2?b?5,9 59&a&b&ap1&bp2?temp595pointer_1&aa9pointer_2&bb59,5UNIX C编程编程yyyy-M- 17age *11.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变
16、量s *p1,int *p2) int *temp,x; temp=&x; *temp=*p1; *p1=*p2; *p2=*temp;main() int a,b,*pointer_1,*pointer_2; scanf(%d,%d,&a,&b); pointer_1=&a; pointer_2=&b; if(ab) s); printf(n%d,%dn,a,b);pointer_1?a?pointer_2?b?59&a&b&ap1&bp29?temp?x&xtemp?x55pointer_1&aa9pointer_2&bb55,9 9,5UNIX C编程编程yyyy-M- 18age *1
17、1.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量s *p1,int *p2) int *temp; temp=p1; p1=p2; p2=temp;main() int a,b,*pointer_1,*pointer_2; scanf(%d,%d,&a,&b); pointer_1=&a; pointer_2=&b; if(ab) s); printf(n%d,%dn,a,b);pointer_1?a?pointer_2?b?59&a&b&ap1&bp2?temp5,9 5,9&atemp&b&apointer_1&aa5pointer_2&bb9UNIX C编程编程yyy
18、y-M- 19age *q 想通过函数调用得到想通过函数调用得到n n个要改变的值,可以:个要改变的值,可以:v 在主调函数中设在主调函数中设n n个变量,用个变量,用n n个指针变量指向它们个指针变量指向它们v 将指针变量作实参,将这将指针变量作实参,将这n n个变量的地址传给所调用的个变量的地址传给所调用的函数的形参函数的形参v 通过形参指针变量,改变该通过形参指针变量,改变该n n个变量的值个变量的值v 主调函数中就可以使用这些改变了值的变量主调函数中就可以使用这些改变了值的变量11.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量UNIX C编程编程yyyy-M- 20
19、age *11.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量 例:输入例:输入a、b、 c3个整数,按大小顺序输出。个整数,按大小顺序输出。main() 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(n%d,%d,%dn,a,b,c);s *pt1, int *pt2) int temp; temp=*pt1; pt1=*pt2; *pt2=temp; exchange(int *q1, int *q2, int *q3) if(*
20、q1*q2) s); if(*q1*q3) s); if(*q2a1a+1UNIX C编程编程yyyy-M- 25age *v 指针的关系运算指针的关系运算 实质是两个地址之间的比较,地实质是两个地址之间的比较,地址大的指针大,地址小的指针小址大的指针大,地址小的指针小 pq p=q pq p=q p=q p!=q11.3 数组与指针数组与指针a2a3a4 2000 2008 a1a020002002200420062008200A2024202220202010pqqpUNIX C编程编程yyyy-M- 26age *v 引用数组元素的方法引用数组元素的方法 int a5,*p; p=a;1
21、1.3 数组与指针数组与指针下标法下标法 ai和和pia2a3a4 2000 a1a020002002200420062008200A2024202220202010p pap0p1p2p3p4指针法指针法 *(a+i)和和* (p+i)pp+1p+2p+3p+4aa+1a+2a+3a+4a2a3a4 2000 a1a020002002200420062008200A2024202220202010p p+5UNIX C编程编程yyyy-M- 27age *v 例例 输出数组中的全部元素输出数组中的全部元素11.3 数组与指针数组与指针main() int a10=1,2,3,4,5,6,7,
22、8,9,10,*p,i; for (i=0;i10;i+) printf(“%4d”,ai);用下标法引用数组元素用下标法引用数组元素UNIX C编程编程yyyy-M- 28age *main() int a10=1,2,3,4,5,6,7,8,9,10,*p,i; for (i=0;i10;i+) printf(“%4d”,*(a+i); 11.3 数组与指针数组与指针 用指针法引用数组元素用指针法引用数组元素 数组名数组名a在计算过程中代表数组的首地址在计算过程中代表数组的首地址 对对ai进行变址运算,转化为进行变址运算,转化为*(a+i)UNIX C编程编程yyyy-M- 29age *
23、 main() int a10=1,2,3,4,5,6,7,8,9,10,*p,i; for (p=a;p(a+10);p+) printf(“%4d”,*p); 11.3 数组与指针数组与指针 p的初值为数组的初值为数组a的起始地址的起始地址 计算过程中使用了指针加法计算过程中使用了指针加法 数组名数组名a在计算过程中代表数组的首地址在计算过程中代表数组的首地址UNIX C编程编程yyyy-M- 30age *main() int a10=1,2,3,4,5,6,7,8,9,10,*p,i; for (p=a,i=0;i10;i+) printf(“%4d”, pi); 11.3 数组与指针
24、数组与指针 用下标法引用数组元素用下标法引用数组元素 p的初值为数组的初值为数组a的起始地址的起始地址UNIX C编程编程yyyy-M- 31age *11.3 数组与指针数组与指针main() int i,*p,a10; p=a; for(i=0;i10;i+) scanf(%d,p+); printf(n); for(i=0;i10;i+,p+) printf(%d,*p);for(i=0;i10;i+) scanf(%d,p); p+; 1 2 3 4 5 6 7 8 9 0 22153 234 0 0 30036 25202 11631 8259 8237 28483a2a3a4 a9
25、 ? ? ? a1a020002002200420062008200A2024202220202010 pp=a;1 2 3 4 5 6 7 8 9 0v例例 通过指针变量输出通过指针变量输出a数组的数组的10个元素个元素UNIX C编程编程yyyy-M- 32age * main() int a =5,8,7,6,2; int y,*p=&a1; y=(*-p)+; printf(%d ,y); printf(%d,a0); 11.3 数组与指针数组与指针a27a36a42 a18a0520002002200420062008200A2024202220202010 pp65y5 6例:例:
26、UNIX C编程编程yyyy-M- 33age *q用数组名作函数参数用数组名作函数参数v 数组名作函数实参,传递给形参的是地址(地址传递)数组名作函数实参,传递给形参的是地址(地址传递) 传递的地址是数组的首地址,形参接收的是数组的首地址传递的地址是数组的首地址,形参接收的是数组的首地址 形参定义时为数组,形参数组的维数可省略(一维数组)形参定义时为数组,形参数组的维数可省略(一维数组) 实际上,编译系统把形参数组名作为指针变量来处理实际上,编译系统把形参数组名作为指针变量来处理11.3 数组与指针数组与指针UNIX C编程编程yyyy-M- 34age * 前面已经分析,前面已经分析,指向
27、数组的指针变量指向数组的指针变量可以通过指针法,也可以通过指针法,也可以可以通过下标法引用数组元素通过下标法引用数组元素,所以,所以11.3 数组与指针数组与指针void f(int b )printf(len of b is %dByten,sizeof(b); printf(a1=%d,b1); main() int a3=1,2,3; f(a);len of b is 2Bytea1=2v 例:例:void f(int *b)printf(a1=%d,*(b+1);1232000bba20002ByteUNIX C编程编程yyyy-M- 35age *v 数组名作函数参数,实参与形参的对
28、应关系数组名作函数参数,实参与形参的对应关系11.3 数组与指针数组与指针实参实参形参形参数组名数组名指针变量指针变量数组名数组名指针变量指针变量数组名数组名数组名数组名指针变量指针变量指针变量指针变量UNIX C编程编程yyyy-M- 36age * 例例 将数组将数组a中中n个整数按相反顺序存放个整数按相反顺序存放11.3 数组与指针数组与指针算法:算法: 设两个设两个“位置指示变量位置指示变量”i和和j,i的初值为的初值为0,j的初值为的初值为n-1 将将ai与与aj交换交换 使使i的值加的值加1,j的值减的值减1 再将再将ai与与aj对换,直到对换,直到i=(n-1)/2为止为止mai
29、n()int i,a10=3,7,9,11,0,6,7,5,4,2; printf(The original array:n); for(i=0;i10;i+)printf(%d,ai); printf(n); inv(a,10); printf(The array has been inverted:n); for(i=0;i10;i+)printf(%d,ai); printf(n);UNIX C编程编程yyyy-M- 37age *void inv(int x ,int n) int temp,i,j,m=(n-1)/2; for(i=0;i=m;i+) j=n-1-i; temp=xi
30、; xi=xj; xj=temp; 11.3 数组与指针数组与指针90a29a311a40 a56 a67 a75 a84 a92a17a0320002002200420062008200A20122010200E200Cm=4a29a311a40 a56 a67 a75 a84 a93a17a0220002002200420062008200A20122010200E200Cm=418a29a311a40 a56 a67 a75 a87 a93a14a0220002002200420062008200A20122010200E200Cm=427a25a311a40 a56 a67 a79 a
31、87 a93a14a0220002002200420062008200A20122010200E200Cm=436a25a37a40 a56 a611 a79 a87 a93a14a0220002002200420062008200A20122010200E200Cm=445xa25a37a46 a50 a611 a79 a87 a93a14a0220002002200420062008200A20122010200E200Cm=45ijUNIX C编程编程yyyy-M- 38age *void inv(int *x,int n) int *p,temp,*i,*j,m=(n-1)/2; i=
32、x;j=x+n-1;p=x+m; for(;i=p;i+,j-) temp=*i; *i=*j; *j=temp; 11.3 数组与指针数组与指针jia29a311a40 a56 a67 a75 a84 a92a17a0320002002200420062008200A20122010200E200Cm=4a29a311a40 a56 a67 a75 a84 a93a17a0220002002200420062008200A20122010200E200Cm=4ija29a311a40 a56 a67 a75 a87 a93a14a0220002002200420062008200A20122
33、010200E200Cm=4ija25a311a40 a56 a67 a79 a87 a93a14a0220002002200420062008200A20122010200E200Cm=4ija25a37a40 a56 a611 a79 a87 a93a14a0220002002200420062008200A20122010200E200Cm=4ijxpa25a37a46 a50 a611 a79 a87 a93a14a0220002002200420062008200A20122010200E200Cm=4ijUNIX C编程编程yyyy-M- 39age *q多维数组与指针多维数组与指
34、针v 多维数组的地址多维数组的地址 int a34=1,3,5,7,9,11,13,15,17,19,21,23; 可以把可以把a看作是一维数组,有看作是一维数组,有3个元素:个元素:a0,a1,a2 a0,a1,a2可以分别认为是包含可以分别认为是包含4个元素的一维数组个元素的一维数组 二维数组是数组的数组二维数组是数组的数组11.3 数组与指针数组与指针a00a01a02a03a10a11a12a13a20a21a22a23aa00a01a02a03a10a11a12a13a20a21a22a23一维数组一维数组aa0a1a2一维数组一维数组a0UNIX C编程编程yyyy-M- 40ag
35、e *11.3 数组与指针数组与指针201620082000a0a1 a2201820102002200020082016a00a01a10a11a20a21a02a03a12a13a22a23aa+1a+2*(*(a+0)+1)元素元素a01可表示为可表示为*(a0+1)a0为数组名,是为数组名,是该数组的首地址该数组的首地址a0+1a1+1a2+1从从a数组中数组中a0可表示可表示*(a+0)所以所以a0+1 *(a+0)+1*(a+1)+1*(a+2)+1UNIX C编程编程yyyy-M- 41age *11.3 数组与指针数组与指针qa-二维数组的首地址,即第二维数组的首地址,即第0行
36、的行的首地址首地址qa+i-第第i行行的首地址的首地址qai *(a+i)-第第i行第行第0列列的元素的元素地址地址qai+j *(a+i)+j -第第i行第行第j列列的的元素地址元素地址q*(ai+j) *(*(a+i)+j) aija+i=&ai=ai=*(a+i) =&ai0,值相等,含义不同值相等,含义不同a+i &ai,表示第表示第i行首地址,指向行行首地址,指向行ai *(a+i) &ai0,表示第表示第i行第行第0列元素地址,指向列元素地址,指向列列UNIX C编程编程yyyy-M- 42age *#define FORMAT%x,%xn#define FORMAT1 %d,%d
37、nmain()int a34=1,3,5,7,9,11,13,15,17,19,21,23; printf(FORMAT,a,*a); printf(FORMAT,a0,*(a+0); printf(FORMAT,&a0,&a00); printf(FORMAT,a1,a+1); printf(FORMAT,&a10,*(a+1)+0); printf(FORMAT,a2,*(a+2); printf(FORMAT,&a2,a+2); printf(FORMAT1,a10,*(*(a+1)+0);11.3 数组与指针数组与指针例例 输出二维数组有关的值。输出二维数组有关的值。ffb8,ffb8
38、ffb8,ffb8ffb8,ffb8ffc0,ffc0ffc0,ffc0ffc8,ffc8ffc8,ffc89,9UNIX C编程编程yyyy-M- 43age *11.3 数组与指针数组与指针201620082000a0a1 a2201820102002200020082016a00a01a10a11a20a21a02a03a12a13a22a23aa+1a+2a0+1a1+1a2+1*(a+0)+1*(a+1)+1*(a+2)+1可认可认为为存储的存储的是数组是数组a0的的首地址首地址*(*(a+0)+1)*(a0+1)UNIX C编程编程yyyy-M- 44age *11.3 数组与指针
39、数组与指针v 指向多维数组元素的指针变量指向多维数组元素的指针变量 指向数组元素的指针变量指向数组元素的指针变量main()int a34=1,3,5,7,9,11,13,15,17,19,21,23; int *p; for(p=a0;pa0+12;p+) if(p-a0)%4=0) printf(n); printf(%4d,*p); 1 3 5 7 9 11 13 15 17 19 21 23p指向数组首指向数组首元素元素第第13个元素个元素的首地址的首地址p指针指向下指针指向下一个元素一个元素UNIX C编程编程yyyy-M- 45age *11.3 数组与指针数组与指针 在在int
40、anm数组中求数组中求aij的首地址的首地址a00a0ja0m-1ai0aijan-10an-1m-1&aij=&a00+i*m+ji行行j列列UNIX C编程编程yyyy-M- 46age *11.3 数组与指针数组与指针 指向由指向由m个元素组成的一维数组的指针变量个元素组成的一维数组的指针变量 定义形式定义形式 数据类型数据类型 (*指针变量名指针变量名)一维数组的维数一维数组的维数 例:例:int (*p)4,可以认为数组名称为,可以认为数组名称为*p(*p)0(*p)1(*p)2(*p)3p p只能指向包含只能指向包含4个元素的一维数组个元素的一维数组(p是该数组的首地址是该数组的首
41、地址) 可让可让p指向二维数组的某一行指向二维数组的某一行 例:例:int a34, (*p)4=a; 一一维数组指针变量维数和二维数组列数必须相同维数组指针变量维数和二维数组列数必须相同*p代表本行第一列的地址代表本行第一列的地址UNIX C编程编程yyyy-M- 47age *11.3 数组与指针数组与指针201820102002200020082016a00a01a10a11a20a21a02a03a12a13a22a23pp+1p+2 *(p)+1*(p+1)+1*(p+2)+1*(*(p+1)+1)UNIX C编程编程yyyy-M- 48age *v 用指向多维数组的指针作函数参数用
42、指向多维数组的指针作函数参数指针变量作形参接受实参数组名传递来的地址时,可以指针变量作形参接受实参数组名传递来的地址时,可以 用指向变量的指针变量用指向变量的指针变量 用指向一维数组的指针变量用指向一维数组的指针变量例例 有一个班,有一个班,3个学生,各学个学生,各学4门课,计算总平均分数,以及门课,计算总平均分数,以及第第n个学生的成绩。个学生的成绩。11.3 数组与指针数组与指针UNIX C编程编程yyyy-M- 49age *11.3 数组与指针数组与指针main() void average(float *p,int n); void search(float (*p)4,int n)
43、; float score34=65,67,70,60,80,87,90,81,90,99,100,98; average(score,12); search(score,2); getch();void average(float *p,int n) float *p_end; float sum=0,aver; p_end=p+n-1;/*最后一行(最后一个学生)最后一列(最后一门成绩)的首地址最后一行(最后一个学生)最后一列(最后一门成绩)的首地址*/ for(;p=p_end;p+) sum=sum+(*p); aver=sum/n; printf(naverage= %5.2f n,
44、aver); void search(float (*p)4,int n) int i; printf(the score of No.%d are:n,n); for(i=0;iy?x:y);11.5 指向函数的指针指向函数的指针UNIX C编程编程yyyy-M- 60age *11.5 指向函数的指针指向函数的指针q 用指向函数的指针作函数参数用指向函数的指针作函数参数 例例 用函数指针变量作参数,求最大值、最小值和两数之和。用函数指针变量作参数,求最大值、最小值和两数之和。 main() int max(int,int); int min(int,int); int add(int,in
45、t); void process(int,int,int (*fun)(); int a,b; 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(%dn,result);max(int x,int y) printf(“max=”);printf(“max=”); return(xy?x:y); return(xy?x:y);min(int x,i
46、nt y) printf(“min=”);printf(“min=”); return(xy?x:y); return(x*y) return x; else return y;main() int a=2,b=3; int *p; p=f1(&a, &b); printf(%dn,*p);2a3b?p调用函数前调用函数前xy*x*y调用函数调用函数2a3b?p2a3bp调用函数后调用函数后UNIX C编程编程yyyy-M- 63age *2a3b?p调用函数前调用函数前11.6返回指针值的函数返回指针值的函数int *f1(int x,int y) if(xy) return &x; els
47、e return &y;main() int a=2,b=3; int *p; p=f1(a, b); printf(%dn,*p);xy调用函数调用函数2a3b?p23调用函数后调用函数后2a3bp?!不能把不能把形参形参或或局部变量局部变量的的地址地址作函数返回值作函数返回值不确定不确定UNIX C编程编程yyyy-M- 64age *11.7指针数组和指向指针的指针指针数组和指向指针的指针q指针数组的概念指针数组的概念v 数组中的元素为指针变量数组中的元素为指针变量 v 定义形式定义形式 数据类型数据类型 *数组名数组名数组长度数组长度 int *p4;char *name5;(元素元素
48、)指针变量所指数据的数据类型指针变量所指数据的数据类型区分区分int *p4与与int (*p)4v 用指针数组执行若干字符串,可以节省内存单元以及处用指针数组执行若干字符串,可以节省内存单元以及处理灵活理灵活Followme0BASIC0GreatWall0FORTRAN0Computerdesign0name0name1name3name2name4Follow meBASICGreat WallFORTRANComputer designname用二维数组,用二维数组,浪费存储空间浪费存储空间UNIX C编程编程yyyy-M- 65age *#include void sort(char
49、 *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; main() char *name=Follow me,BASIC, Great Wall,FORTRAN,Computer ; int n=5; sort(name,n); print(name,n);例:将若干字符串按字母顺序(由小到大)输出例:将若干字符串按字母顺序(由小到大)输出定义指针数组定义指针数组传递指针数组传递指针数组name的首地址
50、的首地址namek,第第k个个字符串字符串的首地址,进的首地址,进行字符串行字符串比较比较元元素交换指针素交换指针void print(char *name,int n) int i; for (i=0;in;i+) printf (%sn,namei);name0name1name3name2name4Follow meBASICGreat WallFORTRANComputer designnamename0name1name3name2name4Follow meBASICGreat WallFORTRANComputer designnameUNIX C编程编程yyyy-M- 66ag
51、e *11.7指针数组和指向指针的指针指针数组和指向指针的指针q指向指针的指针指向指针的指针v 指向指针数据的指针变量指向指针数据的指针变量(即指针变量存放的是指针变即指针变量存放的是指针变量的地址量的地址)v 定义形式定义形式 数据类型数据类型 *指针名指针名最终目标变量的数据类型最终目标变量的数据类型v 例:例: int c=5,*p,*q; p=&c;q=&p; 5c&cp*p&pq*q*q printf(%d,%d,%d,c,*p,*q); 5,5,5UNIX C编程编程yyyy-M- 67age *11.7指针数组和指向指针的指针指针数组和指向指针的指针main()char *a=h
52、ello,world,China,*p; int i; for (p=a,i=0;i3;i+) printf(n*a%d=%s,i,*(p+i);a0helloa1worlda2Chinaapp+1p+2*(a+i)是否可以?是否可以?*a0=hello*a1=world*a2=ChinaUNIX C编程编程yyyy-M- 68age *11.7指针数组和指向指针的指针指针数组和指向指针的指针main()char *a=hello,world,China,*p; int i; p=a; for (i=0;i copy.exe source.c temp.c11.7指针数组和指向指针的指针指针数
53、组和指向指针的指针有有3个字符串参数的命令行个字符串参数的命令行v 带参数的带参数的main函数形式:函数形式:main(int argc, char *argv) 元素指向命令行参数中各元素指向命令行参数中各字符串首地址字符串首地址命令行中参数个数命令行中参数个数命令行命令行 实参表实参表main(形参表形参表)系统自动调用系统自动调用main函数时传递函数时传递v 命令行参数传递命令行参数传递第一个参数第一个参数: main所在所在的的可执行文件名可执行文件名UNIX C编程编程yyyy-M- 70age *11.7指针数组和指向指针的指针指针数组和指向指针的指针/*test.c*/mai
54、n(int argc, char *argv) while(argc1) argv=argv+1; printf(%sn,*argv); -argc; 编译、链接编译、链接test.c,生成可执行文件,生成可执行文件test.exe 在在DOS状态下运行状态下运行(test.exe所在路径下所在路径下) C:TC test.exe hello world!helloworld!v 例例argv0argv1argv2char *argvargvargc=3testhelloworldUNIX C编程编程yyyy-M- 71age *q 指向结构体变量的指针指向结构体变量的指针v 定义形式定义形式
55、 struct 结构体名结构体名 *结构体指针结构体指针名名;11.8 指向结构体的指针指向结构体的指针例例 struct student int num; char name20; char sex; int age; float score; char addr30; ; struct student s,*p; p=&s; pnumname20sexagescoreaddr20sp-nump-namep-sexp-agep-scorep-addr引用成员引用成员(*p).num(*p).name(*p).sex(*p).age(*p).score(*p).addr引用成员引用成员s.nu
56、ms.names.sexs.ages.scores.addr引用成员引用成员UNIX C编程编程yyyy-M- 72age *q 指向结构体数组的指针指向结构体数组的指针11.8 指向结构体的指针指向结构体的指针numname20sexagescoreaddr30stu0stu1stu2pstup+1p+2printf(%5d %-20s %2c %4dn, p-num, p-name, p-sex, p-age);UNIX C编程编程yyyy-M- 73age *q 用指向结构体的指针作为函数参数用指向结构体的指针作为函数参数v 结构体指针做函数参数,结构体指针做函数参数,传地址传地址11.
57、8 指向结构体的指针指向结构体的指针UNIX C编程编程yyyy-M- 74age *11.8 指向结构体的指针指向结构体的指针#define FORMAT %dn%sn%fn%fn%fnstruct student int num; char name20; float score3; stu=12345,Li Li,67.5,89,78.6;main() void print(struct student *); /*形参类型修改成指向结构体形参类型修改成指向结构体的指针变量的指针变量*/ print(&stu); /*实参改为实参改为stu的起始地址的起始地址*/ void print(
58、struct student *p) /*形参类型修改了形参类型修改了*/ printf(FORMAT,p-num,p-name,p-score0,p-score1,p-score2);/*用指针变量调用各成员之值用指针变量调用各成员之值*/ printf(n); UNIX C编程编程yyyy-M- 75age *例:结构体数组作函数参数例:结构体数组作函数参数 打印打印2名学生的名学生的3门成绩门成绩struct student int num; char name20; int score3;stu2;void input(struct student stu1)int i,j; for(
59、i=0;i2;i+) printf(input NO.:); scanf(%d,&stu1i.num); printf(input name:); scanf(%s,stu1i.name); for(j=0;j3;j+) printf(input score%d:,j); scanf(%d,&stu1i.scorej); void print(struct student stu2)int i,j; for(i=0;i2;i+) printf(n NO. %d,stu2i.num); printf(n name %s,stu2i.name); for(j=0;j3;j+) printf(n %
60、d score %d,j+1,stu2i.scorej); main()clrscr(); input(stu); print(stu); getch();UNIX C编程编程yyyy-M- 76age *q链表是一种常见的数据结构,是可以动态地分配存储空间链表是一种常见的数据结构,是可以动态地分配存储空间的一种结构。的一种结构。q数组是一种静态地分配存储空间的方式数组是一种静态地分配存储空间的方式11.9用指针处理链表用指针处理链表head1249C10211475DNULL1021B14751356A13561249ABC Dpq链表的构成:链表的构成:v 头指针,存放一个地址,指向链表的
61、第一个元素头指针,存放一个地址,指向链表的第一个元素v 链表中每个元素称为一个链表中每个元素称为一个“结点结点”,每个结点包括两部,每个结点包括两部分:用户数据和指向下一个结点的地址分:用户数据和指向下一个结点的地址v 最后一个元素称为最后一个元素称为“表尾表尾”,其地址为,其地址为NULL(空地址)(空地址)UNIX C编程编程yyyy-M- 77age *#include struct node /*定义结点类型定义结点类型*/ char data; /*数据域数据域*/ struct node *next; /*指向下一个结点的指针域指向下一个结点的指针域*/ a,b,c,d,*head
62、,*p;11.9用指针处理链表用指针处理链表head?C?1475D?1021B?1356A?1249head=&a;a.next=&b;b.next=&c;c.next=&d;d.next=NULL;p=head;head C 1475DNULL1021B 1356A 1249do printf(%c-,p-data); p=p-next;while (p!=NULL);ppppNULL静态链表:静态链表:需要的节点事先建立需要的节点事先建立pUNIX C编程编程yyyy-M- 78age *q 动态链表动态链表v 所需函数所需函数11.9用指针处理链表用指针处理链表函数名函数名函数原型函数
63、原型功能功能返回值返回值mallocvoid *malloc(unsigned size)分配分配size字节的字节的存储区存储区所分配的内存所分配的内存区起始地址区起始地址freevoid free(*p)释放释放p所指的内所指的内存区存区无无v 定义节点类型定义节点类型#define NULL 0 /*空地址空地址*/#define LEN sizeof(struct node) /*结点长度结点长度*/struct node int data; struct node *next; int n;/*/*表示结点个数表示结点个数* */ /UNIX C编程编程yyyy-M- 79age *
64、q 建立动态链表建立动态链表11.9用指针处理链表用指针处理链表struct node *creat(void)struct node *head,*p,*q; n=0; p=(struct node *)malloc(LEN); scanf(“%d”,&p-data); head=NULL; while (p-num!=0) n+; if (n=1) head=p; /*头指针指向第一个结点头指针指向第一个结点*/ else q-next=p; /*链入新结点链入新结点*/ q=p; /*q指针总是指向链表的最后一个结点指针总是指向链表的最后一个结点*/ p=(struct node *)m
65、alloc(LEN); scanf(“%d”,&p-data); q-next=NULL;/*处理尾结点的指针域处理尾结点的指针域*/ return(head);1p headq 1p3pqq3p5pqq5p0p main()struct node *head; head=creat();UNIX C编程编程yyyy-M- 80age *q 输出链表输出链表11.9用指针处理链表用指针处理链表void print(struct node *head)struct node *p; p=head; if (head!=NULL) do printf( %d,p-data); p=p-next;
66、while(p!=NULL); main()struct node *head; head=creat(); print(head);31p head5 ppppppNULLUNIX C编程编程yyyy-M- 81age *q 链表的删除链表的删除( (删除删除p p所指的结点所指的结点) )11.9用指针处理链表用指针处理链表31p head5 head=p-next;free(p);31q head5 pq-next=p-next;free(p);53 head p p1q head5 UNIX C编程编程yyyy-M- 82age *q 链表的插入(在链表的插入(在q q所指结点前插入新结点所指结点前插入新结点* *s s)11.9用指针处理链表用指针处理链表31q head5 0 s31q head5 s=(struct node*)malloc(LEN);scanf(%d,&s-data);s-next=q;head=s;UNIX C编程编程yyyy-M- 83age *11.9用指针处理链表用指针处理链表31p head5 qs=(struct node*)malloc(LEN);scanf(%d,&s-data);s-next=q;p-next=s;s2