首页计算机计算机软件计算机语言与程序设计 09 指针.ppt

09 指针.ppt

页数:32页文件大小:498.0 KB来源: 计算机语言与程序设计ppt课件

本课件系统讲解指针,先说明内存地址、指针变量的定义与取地址、间接访问运算,再讲指针与一维数组、二维数组的对应关系及指针运算,随后展开字符串指针、字符指针数组与多级指针的用法,并通过对程序运行结果的对照演示,帮助读者建立「逻辑指代与物理指代」的清晰认识。

第九讲指针章节封面页,标示本讲讲解指针这一C语言重要概念
引入故事页,用地下工作者按地址1000找到数据66的故事类比指针
地址说明页,说明66的直接地址为1000、间接地址为211并引出指针变量P
查看本课件的文字版(共 32 页,供检索与复制)

第1页:第九讲指针封面

本页为第九讲 指针章节封面。指针是 C 语言中的一个重要概念,掌握指针的用法可使程序简洁、高效、灵活。

第2页:寻找密钥的小故事

为了了解什么是指针,先看一个小故事:地下工作者阿金接到上级指令,要去寻找打开密电码的密钥,这是一个整数。几经周折,才探知如下线索,密钥藏在一栋三年前就被贴上封条的小楼中。

一个风雨交加的夜晚,阿金潜入了小楼,房间很多,不知该进哪一间,正在一筹莫展之际,忽然走廊上的电话铃声响起。艺高人胆大,阿金毫不迟疑,抓起听筒,只听一个陌生人说:“去打开 211 房间,那里有线索”。阿金疾步上楼,打开 211 房间,用电筒一照,只见桌上赫然 6 个大字:地址 1000。阿金眼睛一亮,迅速找到 1000 房间,取出重要数据 66,完成了任务。

第3页:直接地址与间接地址

我们画出下图:

  • 数据藏在一个内存地址单元中,地址是 1000
  • 地址 1000 又由 P 单元所指认,P 单元的地址为 211
  • 66 的直接地址是 1000;66 的间接地址是 211;211 中存的是直接地址 1000
  • 称 P 为指针变量,1000 是指针变量的值,实际上是有用数据藏在存储器中的地址

第4页:指针的概念

指针变量——用来存放另一变量地址的变量,变量的指针就是变量的地址。

1、指针的概念:指针是一种特殊的变量,特殊性表现在类型和值上。从变量讲,指针也具有变量的三个要素:

  • 变量名,这与一般变量取名相同,由英文字符开始
  • 指针变量的类型,是指针所指向的变量的类型,而不是自身的类型
  • 指针的值是某个变量的内存地址

第5页:指针的定义

从上面的概念可知,指针本身类型是 int 型,因为任何内存地址都是整型的,但是指针变量的类型却定义成它所指向的变量的类型。

2、指针的定义(说明,先说明后引用),例如:

int *p, *q;float *point;double *pd;int (*pa)[10];int (*pu)();int **qq; 

第6页:指针的赋值

3、指针赋值,例:

int akey;int *p,*q;akey=66;p = &akey;q = p; 

第7页:指针赋值示意图

本页以图形方式展示 q = p 之后两个指针指向同一变量的情形(图2),源文件未给出更多文字说明。

第8页:指针1.c示例程序

//指针1.c #include <stdio.h>void main(){ int a[5]={0,1,2,3,4}; int *p1,*p2; p1=&a[1]; p2=&a[2]; printf("a[1]=%d;a[2]=%d\n",*p1,*p2);} 

第9页:取地址与间接访问运算符

说明:见图 p1 和 p2 分别指向 a[1]、a[2],这里

  • &——取地址运算符
  • *——指针运算符(间接访问运算符)
  • *p1——间接访问 p1 所指向的内存单元,当然是输出 a[1] 的值
  • *p2——间接访问 p2 所指向的内存单元,当然是输出 a[2] 的值

第10页:指针2.c示例程序

//指针2.c #include <stdio.h>void main(){ int akey,b; int *p,*q; akey=66; p=&akey; q=&b; *q=*p; printf("b=%d\n",b); printf("*q=%d\n",*q);} 

第11页:向指针所指单元赋值

本页以图形方式展示向指针所指向的内存单元赋值(*q=*p)的效果,源文件未给出更多文字说明。

第12页:指针3.c示例程序

//指针3.c #include <stdio.h>void main(){ int a[5]={1,3,5,7,9}; int *p; int i; p=a; for(i=0;i<5;i=i+1) { printf("a[%d]=%d\n",i,*p); p=p+1; }} 

第13页:指针与数组的等价关系

说明:

  1. p=a; 这里数组名作为数组的起始地址,即 a[0] 的地址。因此 p=a 等效于 p=&a[0];
  2. p=p+1; 如 p 指向 a[0],则 p=p+1 之后,p 指向 a[1]
  3. 如果 p=a 等效于 p=&a[0];,则 p=a+4 等效于 p=&a[4];

a[0]、a[1]、…、a[4] 可分别用 *p、*(p+1)、…、*(p+4) 表示,二者等效。

第14页:指针4.c示例程序

//指针4.c #include <stdio.h>void main(){ int a[5]={1,3,5,7,9}; int *p; int i=0; for(p=a;p<a+5;p=p+1) { printf("a[%d]=%d\n",i,*p); i=i+1; }} 

第15页:指针5.c示例程序

//指针5.c #include <stdio.h> void main() { char *p; static char s[] = "abcdefgh"; p=s; while (*p != '\0') { p=p+1; } printf("字串长度为%d\n",p-s);}

数组名是一个常量指针,指向该数组的首地址,例:

第16页:常量指针与数组首地址

图中数组的首地址是 s[0] 的地址,即 &s[0]。s 可看作是指向 s[0] 的指针。s 是不会动的,是常量指针。

  • 下标 0~7 依次存放字符 a~h,下标 8 存放串结束标志 \0
  • 指针 p 可在数组内前后移动,而 s 固定指向首元素

第17页:指针6.c示例程序

//指针6.c #include <stdio.h>void main(){ static char shuzi[]="987654321"; char *p=&shuzi[8]; do { putchar(*p); p=p-1; } while (p>=shuzi); putchar('\n');}

数组名是一个常量指针,指向该数组的首地址,例:

第18页:指针6.c的说明

说明:

  1. 字符串:数字字符串
  2. p 指向 shuzi[8],即指向串中的字符 '1'
  3. 直到型循环,用 putchar 函数将 shuzi[8] 输出到屏幕;之后让 p=p-1
  4. 在 while 中,当 p>=shuzi 则继续执行循环体,一旦 p<shuzi 则退出循环。这种做法使输出结果为 123456789
  5. 在本例中数组名 shuzi 是一个常量指针,永远指向 shuzi[0] 的地址上

思考:如何通过 p 和 shuzi 求该数字字符串的长度?

第19页:指针7.c示例程序

//指针7.c #include <stdio.h>void main(){ int i; char *p; p="computer"; printf("%s\n",p); for (i=0;i<8;i=i+1) { putchar(p[i]); } putchar('\n'); while(*p) { putchar(*p); p=p+1; } putchar('\n');} 

第20页:字符指针与字符数组的赋值

上例中有三种不同的输出方式,请你自己分析一下,各有什么特点。

说明:

  1. 对字符指针变量赋值的写法:
(1)char *p; (2)char *p="computer"; p = "computer";

以上两种都行,可以整体赋值。

  1. 对字符数组赋初值的写法:
(1)char as[12]="department"; char as[] ="department";(2)char as[12]; as = "department"; as[12]="department"; 

第21页:例题分析的定义部分

#include <stdio.h>void main(){ int i; char s[ ] = "China"; char* t = s ; char* p[ ]={"China","Canada","Denmark","Greece"}; char** q[ ]={p,p+2,p+3,p+1};

例题分析。

第22页:第一组输出语句

//输出1.1:s的地址 cout<<"1.1:输出s的地址"<<&s<<endl;cout<<"1.2:输出s的内容"<<s<<endl;cout<<"1.3:输出t指向的内容"<< t <<endl;cout<<"1.4:输出*t表示的内容"<< *t<<endl;cout<<"1.5:输出*s表示的内容"<< *s <<endl;cout<<"1.6:输出t所在的地址"<< &t<<endl;

第23页:第一组输出结果

第一组输出的结果
输出项说明输出值
1.1s 的地址0x0012FF78
1.2s 的内容China
1.3t 指向的内容China
1.4*t 表示的内容C
1.5*s 表示的内容C
1.6t 所在的地址0x0012FF74

第24页:第二组输出语句

//输出2.1: P[0]指向的字符串 cout<<"2.1:输出P[0]指向的字符串"<<p[0]<<endl;cout<<"2.2:输出P[1]指向的字符串"<<p[1]<<endl;cout<<"2.3:输出P[2]指向的字符串"<<p[2]<<endl;cout<<"2.4:输出P[3]指向的字符串"<<p[3]<<endl;

第25页:第二组输出结果

第二组输出的结果
输出项说明输出值
2.1P[0] 指向的字符串China
2.2P[1] 指向的字符串Canada
2.3P[2] 指向的字符串Denmark
2.4P[3] 指向的字符串Greece

第26页:第三组输出语句

//输出3.1: p[0]本身的地址 cout <<"3.1:输出p[0]本身的地址"<<&p[0]<< endl;cout <<"3.2:输出p[1]本身的地址"<<&p[1]<< endl;cout <<"3.3:输出p[2]本身的地址"<<&p[2]<< endl;cout <<"3.4:输出p[3]本身的地址"<<&p[3]<< endl;

第27页:第三组输出结果

第三组输出的结果
输出项说明输出值
3.1p[0] 本身的地址0x0012FF64
3.2p[1] 本身的地址0x0012FF68
3.3p[2] 本身的地址0x0012FF6C
3.4p[3] 本身的地址0x0012FF70

第28页:第四组输出语句

//输出4.1: q[0]指向的内容 cout << "4.1:输出q[0]指向的内容" << q[0] << endl;cout << "4.2:输出q[1]指向的内容" << q[1] << endl;cout << "4.3:输出q[2]指向的内容" << q[2] << endl;cout << "4.4:输出q[3]指向的内容" << q[3] << endl;

第29页:第四组输出结果

第四组输出的结果(q 元素指向的指针地址)
输出项说明输出值
4.1q[0] 指向的内容0x0012FF64(即 &p[0])
4.2q[1] 指向的内容0x0012FF6C(即 &p[2])
4.3q[2] 指向的内容0x0012FF70(即 &p[3])
4.4q[3] 指向的内容0x0012FF68(即 &p[1])

第30页:第五组输出语句

//输出5.1: q[0]指向的内容的内容 cout << "5.1:输出q[0]指向的内容的内容" << *q[0] << endl;cout << "5.2:输出q[1]指向的内容的内容" << *q[1] << endl;cout << "5.3:输出q[2]指向的内容的内容" << *q[2] << endl;cout << "5.4:输出q[3]指向的内容的内容" << *q[3] << endl;

第31页:第五组输出结果

第五组输出的结果(对 q 元素做两级间接访问)
输出项说明输出值
5.1q[0] 指向的内容的内容China
5.2q[1] 指向的内容的内容Denmark
5.3q[2] 指向的内容的内容Greece
5.4q[3] 指向的内容的内容Canada

第32页:第九讲结束页

本页为第九讲 指针的结束页,本讲内容至此结束。