《C语言第7章指针第1讲课件.ppt》由会员分享,可在线阅读,更多相关《C语言第7章指针第1讲课件.ppt(50页珍藏版)》请在三一文库上搜索。
1、第7章 指针 (一),C语言程序设计,内容提要,指针概述 指针的概念 为什么引入指针的概念 指针变量作为函数参数 字符指针作为函数参数 指针和数组间的关系 一维数组的地址和指针 二维数组的地址和指针,为什么引入指针的概念,铁杆C/C+程序员最挚爱的武器:指针 C/C+的高效、高能主要来自于指针 很多不可能的任务由指针完成,为什么引入指针的概念,指针 为函数提供修改变量值的手段 为C的动态内存分配系统提供支持 为动态数据结构(如例链表、队列、二叉树等)提供支持 可以改善某些子程序的效率,内存的寻址方式,如何读写内存中的数据? 通过变量的地址访问变量所在的存储单元 两种寻址方式 直接(寻址)访问
2、通过变量地址直接存取变量内容 间接(寻址)访问 通过指针变量来间接存取它所指向的变量 i_pointer=,指针(Pointer)的概念,指针也是一种数据类型 指针变量 声明为指针类型的变量,专门存放地址数据的变量,如何定义指针变量?,定义指针变量 int *p; 定义了一个指针变量p,简称指针p p是变量,int*是类型 指针变量初始化 int *p,a; p = *p 与 a 完全等价,int i,*p; p=,int *p; float *q; p=q;,int i; float *p; p=,int *p; p=100;,判断是真?是假?,指针变量只 存放地址!,一个指针变量不能指向与
3、其类型不同的变量!,我是真的, 你猜对了吗?,应在类型相同的指针变量之间赋值,&与*操作符,&用来取变量的地址 *用来取指针指向的内存中的内容,int *p, a10; p = ,int i=3, *p; p = ,指针变量与其它类型变量的对比,共性 在内存中占据一定大小的存储单元 先定义,后使用 特殊性 它的内容只能是地址,而不能是数据 必须初始化后才能使用,否则指向不确定的存储单元,对该空间进行访问,将可能造成危险 可参与的运算:加、减一个整数,自增、自减、关系、赋值 只能指向同一基类型的变量,指针的指向,只能指向同一基类型的变量,否则将引起warning float x; int *p
4、= TC编译 warning: Suspicious pointer conversion in function main VC编译 warning C4133: = : incompatible types - from float * to int *,指针运算,算术运算 short *p, a10; p = a; p+; /*p的值增加多少?*/ 指针的加减运算是以其指向的类型的字节长度为单位的,6000 6001 6002 6003 6004 6005 6006,指针运算,int *p, *q, a10; p = a; q = 指针运算不能乱算 一般只进行指针和整数的加减运算,同类型
5、指针之间的减法运算 其它运算,比如乘法、除法、浮点运算、指针之间的加法等,并无意义,所以也不支持,指针运算,关系运算 指向同一种数据类型的两个指针才能进行关系运算 值为1或0 p q p q p = q 不能与非指针类型变量进行比较,但可与NULL(即0值)进行等或不等的关系运算 判断p是否为空指针 P = NULL p != NULL,指针运算,赋值运算 指针在使用前一定要赋值 为指针变量赋的值必须是一个地址,main() int *p; scanf(“%d“,p); ,main() int a,*p= ,错! 但TC下不报错 VC下报错,指针与函数,指针既然是数据类型,自然可以做函数参数和
6、返回值的类型 指针做函数参数的经典例子: 两数的互换,void Swap(int *x,int *y) int temp; temp = *x; *x = *y; *y = temp; ,main() int a, b; a = 15; b = 8; Swap( ,void Swap(int x,int y) int temp; temp = x; x = y; y = temp; ,main() int a, b; a = 15; b = 8; Swap(a, b); printf(“a=%d,b=%d“,a,b); ,程序 1,程序 2,例7.17.2:编写函数实现两数的互换,实 参,形
7、参,结果有何不同?,Not Work!Why?,主调函数,被调函数,main() int a, b; a = 15; b = 8; Swap(a, b); printf(“a=%d,b=%d“,a,b); ,void Swap(int x, int y) int temp; temp = x; x = y; y = temp; ,5,5,a,b,实 参,形 参,9,9,程序 1,x,y,5,5,temp,9,主调函数,被调函数,main() int a, b; a = 15; b = 8; Swap( ,void Swap(int *x, int *y) int temp; temp = *x
8、; *x = *y; *y = temp; ,&a,&a,实 参,形 参,&b,&b,程序 2,x,y,5,temp,5,a,b,9,9,5,简单变量作函数参数与指针变量作函数参数的比较,swap函数的几种错误形式(1/3),参数单向传递 void Swap(int x, int y) int temp; temp = x; /*x,y为内部变量*/ x = y; y = temp; ,swap函数的几种错误形式(2/3),参数单向传递 void Swap(int *p1, int *p2) int *p; p = p1; /*p1,p2为内部变量*/ p1 = p2; p2 = p; ,sw
9、ap函数的几种错误形式(3/3),指针p没有确切地址 void Swap(int *p1, int *p2) int *p; /*指针p未初始化*/ *p = *p1; *p1 = *p2; *p2 = *p; ,字符串与字符数组、字符指针,C语言并没有为字符串提供任何专门的表示法,完全使用字符数组和字符指针来处理 字符串 一串以0结尾的字符 字符数组 每个元素都是字符类型的数组 char string100; 字符指针 指向字符类型的指针 char *p; 数组和指针可以等同看待,上面三者本质上是一回事,字符指针变量与字符数组的区别,定义方法不同 char str10; char *ptr;
10、 赋值方法不同 char str10; str = ”china”; /*错误*/ strcpy(str,”china”); /*正确*/ char *ptr; ptr = ”china”; 字符指针是变量,而数组名是地址常量,使用字符指针的注意事项,字符指针变量必须有明确的指向,否则使用是危险的 例如,输入字符串时 char *a; scanf(“%s“, a); /*错误*/ 应为: char *a; char str10; a = str; scanf(“%s“, a); /*正确*/,例7.5 :字符串拷贝用字符数组编程,void MyStrcpy(char dstStr, char
11、srcStr) int i = 0; while (srcStri != 0) dstStri = srcStri; i+; dstStri = 0; ,void MyStrcpy(char *dstStr, const char *srcStr) while (*srcStr != 0) *dstStr = *srcStr; srcStr+; dstStr+; *dstStr = 0; ,当只允许函数访问地址内容,不允许修改时,可以把函数的指针参数定义为const,例7.5 :字符串拷贝用字符指针编程,例7.5 :字符串拷贝主函数程序,#include main() char a80, b8
12、0; printf(“Please enter a string:”); gets(a); MyStrcpy(b,a); printf(“The copy is:”); puts(b); ,例7.6 :计算实际字符个数,unsigned int MyStrlen(char str) int i; unsigned int len = 0; for (i=0; stri!=0; i+) len+; return (len); ,unsigned int MyStrlen(char *pStr) unsigned int len = 0; for (; *pStr!=0; pStr+) len+;
13、 return (len); ,方法2:用字符指针实现,方法1:用字符数组实现,指针与数组,数组名就是一个指针 只是不能修改这个指针的指向 可以定义函数的参数为数组 指针也可当作数组名使用 short *p, a10; p = a; 数组元素的几种等价引用形式 ai *(a+i) pi *(p+i),6000 6001 6002 6003 6004 6005 6006 6007,a,a+1,a+2,6000 6001 6002 6003 6004 6005 6006 6007,a,p+,p+,输入输出数组的全部元素,main() int a10; int i; for (i=0; i10; i
14、+) scanf(“%d“, ,方法1:下标法,main() int a10; int *p, i; for (p=a; p(a+10); p+) scanf(“%d“, p); for (p=a; p(a+10); p+) printf(“%d “, *p); ,方法2:指针法,例7.7 :插入排序,关键是:找到该插入的位置,然后依次移动插入位置及其后的所有元素腾出这一位置放入待插入的元素,例7.7 :插入排序主函数,#include #define ARR_SIZE 10 void Inseart(int a,int n, int x) main() /*教材268页*/ int aARR
15、_SIZE+1, x, i, n; Inseart(a, n, x); /*调用函数 实参a为数组名*/ ,例7.7 :插入排序数组作形参,void Inseart(int a, int n, int x) int i, pos; for (i=0; (i ai); i+) pos = i; for (i = n-1; i = pos; i-) ai+1 = ai; /*向后移动*/ apos = x; /*插入元素x到位置pos*/ ,main() /*教材270页*/ int aARR_SIZE+1, x, i, n; Inseart(a, n, x); /*调用函数 实参a为数组名*/
16、void Inseart(int *a, int n, int x) /*定义函数,形参a为指针变量*/ ,插入排序方式二,main() /*教材270页*/ int aARR_SIZE+1, x, i, n; int *p = NULL; Inseart(p, n, x); /*调用函数 实参p指针变量*/ void Inseart(int a, int n, int x) /*定义函数,形参a为数组*/ ,插入排序方式三,main() /*教材270页*/ int aARR_SIZE+1, x, i, n; int *p = NULL; Inseart(p, n, x); /*调用函数 实
17、参p为指针变量*/ void Inseart(int *a, int n, int x) /*定义函数,形参a为指针变量*/ ,插入排序方式4,例7.7 :插入排序指针作形参,void Inseart(int *a, int n, int x) int i, pos; for (i=0; (i *(a+i); i+) pos = i; for (i = n-1; i = pos; i-) *(a + i + 1) = *(a + i); /*向后移动*/ *(a + pos) = x; /*插入元素x到位置pos*/ ,指针与二维数组,C语言将二维数组看作一维数组,其每个数组元素又是一个一维数
18、组 按行顺序存放所有元素,a a0+0,a+1 a1+0,a0+1,a0+2,&a00,&a10,&a11,a1+1,&a12,&a01,&a02,a1+2,int a23;,例7.8,任意输入英文的星期几,在查找星期表后输出其对应的数字。 char weekDay710 = “Sunday“, “Monday“, “Tuesday“,“Wednesday“, “Thursday“, “Friday“, “Saturday“;,表7-1 星期表的内容,#include main() int i, pos; int findFlag = 0; char x10; char weekDay10 =
19、 “Sunday“,“Monday“,“Tuesday“, “Wednesday“,“Thursday“,“Friday“, “Saturday“; printf(“Please enter a string:“); scanf(“%s“, x); for (i=0; i 7 ,例7.8,指针与二维数组,a 代表二维数组的首地址,第0行的地址 a+i 代表第i行的地址 *(a+i) 即 ai 代表第i行第0列的地址 *(a+i)+j 即 ai+j 代表第i行第j列的地址 *(*(a+i)+j ) 即 aij 代表第i行第j列的元素,行地址转变成列地址,指针与二维数组,二维数组的指针列指针 in
20、t *p; p = *a;/用列地址初始化 逐个元素查找元素所在位置 相对于数组起始地址的偏移量 i*n+j for (i=0; im; i+) for (j=0; jn; j+) printf(“%d“,*(p+i*n+j);,p,p+,指针与二维数组,二维数组的指针行指针 int (*p)3, a43,*p1; p = a;/用行地址初始化 p1=a0 ;/用元素地址初始化 先逐行查找元素所在行 再在行内逐列查找元素所在位置 for (i=0; im; i+) for (j=0; jn; j+) printf(“%d“,*(*(p+i)+j);,p,p+,例7.3:在一个班级中找出最高分及
21、其学号,void FindMax(float score, long num, int n, float pMaxScore, long pMaxNum) int i; pMaxScore = score0; pMaxNum = num0; for (i=1; i pMaxScore) pMaxScore = scorei; pMaxNum = numi; ,能返回这两个值吗?,例7.3:在一个班级中找出最高分及其学号,void FindMax(float score, long num, int n, float *pMaxScore, long *pMaxNum) int i; *pMax
22、Score = score0; *pMaxNum = num0; for (i=1; i *pMaxScore) *pMaxScore = scorei; *pMaxNum = numi; ,指针参数指定了存放这两个值的地址,例7.9 :在多个班级中找出最高分及其所在班级和学号,int FindMax(int pmn, int m, int n, int *pRow, int *pCol) int i, j, max; max = p00; *pRow = 0; *pCol = 0; for (i=0; i max) max = pij; *pRow = i; *pCol = j; retur
23、n (max); ,能这样传递m个班(每班n个学生)的成绩吗?,int FindMax(int *p, int m, int n, int *pRow, int *pCol) int i, j, max; max = p0; *pRow = 0; *pCol = 0; for (i=0; i max) max = pi*n+j; *pRow = i; *pCol = j; return (max); ,指定存储m个班(每班n个学生)成绩的首地址,例7.9 :在多个班级中找出最高分及其所在班级和学号,指针、数组以及其它的类型混合,基本数据类型 int、long、char、short、float、double 指针是一种数据类型 是从其它类型派生的类型 XX类型的指针 数组也是一种数据类型 是从其它类型派生的类型 每个元素都有一个类型 任何类型都可以做指针或者数组的基础类型 它们自己也可以做彼此或自己的基础类型,
链接地址:https://www.31doc.com/p-3479719.html