第十章指针2学时一教学目的及要求本章节是C语言程序设计中的Word文档格式.docx
- 文档编号:4747090
- 上传时间:2023-05-04
- 格式:DOCX
- 页数:20
- 大小:40.54KB
第十章指针2学时一教学目的及要求本章节是C语言程序设计中的Word文档格式.docx
《第十章指针2学时一教学目的及要求本章节是C语言程序设计中的Word文档格式.docx》由会员分享,可在线阅读,更多相关《第十章指针2学时一教学目的及要求本章节是C语言程序设计中的Word文档格式.docx(20页珍藏版)》请在冰点文库上搜索。
每个内存单元都有一个唯一的编号,这个编号就是内存单元的地址,根据内存单元的地址就可以找到所需的内存单元,所以通常也把这个地址称为指针。
例如,图一为一段连续的内存单元,每一格为一个内存单元,依次对其进行编号,假设编号从2000开始
如果在程序中定义了变量,在程序被调入内存运行后,系统会根据变量的类型为变量分配一定的存储单元,用来存放该变量的值。
不同的数据类型所占用的内存单元数不等,如整型量占2个内存单元,字符量占1个内存单元,单精度浮点型占4个内存单元等.
例如:
程序中有如下声明语句:
inti,j;
chara[4];
floatk;
内存分配的情况如图二.一变量所占的第一个内存单元的地址作为变量的地址.则变量i的地址为2000,j的地址为2002,数组a的首地址为2004,k的地址为2008.
2.内存单元的内容:
指内存单元中存放的数据。
例如:
给以上定义的变量赋值如下:
i=2;
j=3;
a[0]=’a’;
a[1]=’b’;
a[2]=’c’;
a[3]=’d’;
k=2.5;
程序运行将变量的值存放到变量所对应的内存单元中.如图三.内存单元的地址类似于抽屉的编号,而内存单元的内容类似于抽屉内存放的东西.
定义指针的目的是为了通过指针去访问内存单元中的内容。
二、指针变量的类型说明
指针变量同普通变量一样,使用之前要定义说明,一般形式为:
类型说明符*指针变量名;
其中,*表示这是一个指针变量名,类型说明符表示本指针变量所指向的变量的数据类型。
例如:
int*p1;
表示p1是一个指针变量,它的值是某个整型变量的地址。
或者说p1指向一个整型变量。
再如:
float*p2;
/*p2是指向浮点变量的指针变量*/
char*p3;
/*p3是指向字符变量的指针变量*/
应该注意的是,一个指针变量只能指向同类型的变量,如P2只能指向浮点变量,不能时而指向一个浮点变量,时而又指向一个字符变量。
6.3指针变量的赋值
指针变量在使用之必须赋予具体的值,未经赋值的指针变量指向的存储单元是随机的,不能使用,否则将造成系统混乱,甚至死机。
C语言中提供了地址运算符&
来表示变量的地址。
其一般形式为:
&
变量名;
如&
a变示变量a的地址,&
b表示变量b的地址。
如要把整型变量a的地址赋予p可以有以下两种方式:
(1)在定义指针变量时初始化
inta;
intp=&
a;
(2)先定义,后赋值
inta;
intp;
p=&
/*p指向a所代表的单元*/
指针变量的赋值只能赋予地址,决不能赋予任何其它数据,否则将引起错误。
不允许把一个数赋予指针变量,故下面的赋值是错误的:
int*p;
p=1000;
被赋值的指针变量前不能再加“*”说明符,如写为intp;
*p=&
也是错误的.
指针变量可以赋值为0,表示空指针,不指向任何的存储单元,可以使用.与不赋初值不同.
二、指针变量的运算
指针变量可以进行某些运算,但其运算的种类是有限的。
它只能进行赋值运算和部分算术运算及关系运算。
1.指针运算符
(1)取地址运算符&
取地址运算符&
是单目运算符,其结合性为自右至左,其功能是取变量的地址。
a表示获取变量a的地址。
(2)取内容运算符*
取内容运算符*是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量(即指针所指向的内容)。
在*运算符之后跟的变量必须是指针变量。
main(){
inta=5,*p=&
/*指针变量p取得了整型变量a的地址*/
printf("
%d"
*p);
/**p代表a,本语句表示输出变量a的值*/
}
inta=10,b=20,s,t,*pa,*pb;
pa=&
pb=&
b;
s=*pa+*pb;
t=*pa**pb;
printf("
a=%d\nb=%d\na+b=%d\na*b=%d\n"
a,b,a+b,a*b);
s=%d\nt=%d\n"
s,t);
需要注意的是指针运算符*和指针变量说明中的指针说明符*不是一回事。
在指针变量说明中,“*”是类型说明符,表示其后的变量是指针类型。
而表达式中出现的“*”则是一个运算符用以表示指针变量所指的变量。
2.指针变量的运算
(1)赋值运算
指针变量的赋值运算有以下几种形式:
(A)一个指针变量的值赋予指向相同类型变量的另一个指针变量。
如:
inta,*pa=&
a,*pb;
pb=pa;
/*把a的地址赋予指针变量pb*/
由于pa,pb均为指向整型变量的指针变量,因此可以相互赋值。
(B)把数组的首地址赋予指向数组的指针变量。
inta[5],*pa;
pa=a;
(数组名表示数组的首地址,故可赋予指向数组的指针变量pa)
也可写为:
pa=&
a[0];
/*数组第一个元素的地址也是整个数组的首地址,也可赋予pa*/
当然也可采取初始化赋值的方法:
inta[5],*pa=a;
(C)把字符串的首地址赋予指向字符类型的指针变量。
例如:
char*pc;
pc="
clanguage"
;
或用初始化赋值的方法写为:
char*pc="
CLanguage"
这里是把存放该字符串的字符数组的首地址装入指针变量。
在后面还将详细介绍。
(D)把函数的入口地址赋予指向函数的指针变量。
例如:
int(*pf)();
pf=f;
/*f为函数名*/
(2)加减算术运算
inta[5],*pa;
pa=a;
/*假设pa所指向的数组元素的下标为i,i=0*/
对于指向数组的指针变量,可以加上或减去一个整数n。
设pa是指向数组a的指针变量,则pa+n,pa-n,pa++,++pa,pa--,--pa运算都是合法的。
pa+n或pa-n指向下标为i+n或i-n的数组元素,即使当前指针向前或向后移动(n*k)个字节。
/*pa指向数组a,也是指向a[0]*/
pa=pa+2;
/*pa指向a[2],即pa的值为&
pa[2]*/
指针变量的加减运算只能对数组指针变量进行,对指向其它类型的指针变量作加减运算是毫无意义的。
(3)两个指针变量之间的运算
只有指向同一数组的两个指针变量之间才能进行运算,否则运算毫无意义。
①两指针变量相减
两指针变量相减所得之差是两个指针所指数组元素之间相差的元素个数。
floata[10];
float*pf1=&
a[2],pf2=&
a[6];
inti=pf2-pf1;
i=4,表示pf1和pf2之间相差4个元素。
两个指针变量进行加法运算毫无实际意义。
②两指针变量进行关系运算
指向同一数组的两指针变量进行关系运算可表示它们所指数组元素之间位置关系。
pf1==pf2表示pf1和pf2指向同一数组元素
pf1>
pf2表示pf1处于高地址位置
pf1<
pf2表示pf2处于低地址位置
pf1==0表示pf1是一个空指针
pf1!
=0表示pf1不是一个空指针
三、指向数组的指针变量
1.在讨论指向数组的指针变量之前,我们先明确几个关系。
(1)数组的首地址:
一个数组被存放在一块连续的内存单元中。
数组名就是这块连续内存单元的首地址。
inta[10];
数组的首地址为a;
(2)数组元素的地址:
每个数组元素按其类型不同占有几个连续的内存单元。
一个数组元素的地址也是指它所占有的几个内存单元的首地址。
数组的首地址即为数组的第一个元素的地址。
数组的首地址也可表示为&
(3)一个指针变量既可以指向一个数组,也可以指向一个数组元素。
floata[10];
float*p1,*p2;
p1=a;
/*与p1=&
a[0]等价*/
p2=&
a[2];
2.使用指针变量访问数组元素
指针变量指向数组后,就可以用指针变量来访问数组元素了,有以下两种方法:
第一种下标法,即用a[i]形式访问数组元素。
inta[5],i,*pa;
pa[0]=5;
/*与a[0]=5等价*/
pa[1]=6;
/*与a[1]=6等价*/
第二种指针法,即采用*(pa+i)形式,用间接访问的方法来访问数组元素。
inta[5],*pa;
*pa=0;
/*与a[0]=5等价*/
*(pa+1)=1;
/*与a[1]=1等价*/
*(pa+2)=2;
/*与a[2]=2等价*/
可利用循环给数组元素赋值
for(i=0;
i<
5;
i++){
*pa=i;
pa++;
for(i=0;
a[%d]=%d\n"
i,*pa);
pa++;
下面,另举一例,该例与上例本意相同,但是实现方式不同。
inta[5],i,*pa=a;
){
printf("
i++,*pa++);
五、数组名和数组指针变量作函数参数
在前面曾经介绍过用数组名作函数的实参和形参的问题。
在学习指针变量之后就更容易理解这个问题了。
数组名就是数组的首地址,实参向形参传送数组名实际上就是传送数组的地址,形参得到该地址后也指向同一数组。
这就好象同一件物品有两个彼此不同的名称一样。
同样,指针变量的值也是地址,数组指针变量的值即为数组的首地址,当然也可作为函数的参数使用。
floatsco[5],av,*sp;
inti;
sp=sco;
\ninput5scores:
\n"
);
i++)scanf("
%f"
&
sco[i]);
av=aver(sp);
averagescoreis%5.2f"
av);
floataver(float*pa){
floatav,s=0;
i++)s=s+*pa++;
av=s/5;
returnav;
六、指向二维数组的指针变量
(一)二维数组地址的表示方法
设有整型二维数组a[3][4]如下:
0123
4567
891011
C语言允许把一个二维数组分解为多个一维数组来处理。
因此数组a可分解为三个一维数组,即a[0]数组:
a[0][0],a[0][1],a[0][2],a[0][3]
a[1]数组:
a[1][0],a[1][1],a[1][2],a[1][3]
a[2]数组:
a[2][0],a[2][1],a[2][2],a[2][3]
数组及数组元素的地址表示如下:
数组的首地址:
*a或a[0]
第一个一维数组的首地址:
a[0]
第二个一维数组的首地址:
a[1]
第三个一维数组的首地址:
a[2]
另外,a+i,a[i],*(a+i),&
a[i][0]是等同的,表示第i个一维数组的首地址。
a[i][j]、*(a+i)+j、a[i]+j等价,表示数组元素a[i][j]的地址。
inta[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
%d,%d,%d,%d,%d,\n"
a,*a,a[0],&
a[0],&
a[0][0]);
a+1,*(a+1),a[1],&
a[1],&
a[1][0]);
a+2,*(a+2),a[2],&
a[2],&
a[2][0]);
%d,%d\n"
a[1]+1,*(a+1)+1);
*(a[1]+1),*(*(a+1)+1));
运行结果为:
-64,-64,-64,-64,-64,
-56,-56,-56,-56,-56,
-48,-48,-48,-48,-48,
-54,-54
5,5
(二)指向二维数组的指针变量
把二维数组a分解为一维数组a[0],a[1],a[2]之后,设p为指向二维数组的指针变量。
可定义为:
int(*p)[4]它表示p是一个指针变量,它指向二维数组a或指向第一个一维数组a[0],其值等于a,a[0],或&
a[0][0]等。
而p+i则指向一维数组a[i]。
从前面的分析可得出*(p+i)+j是二维数组i行j列的元素的地址,而*(*(p+i)+j)则是i行j列元素的值。
二维数组指针变量说明的一般形式为:
类型说明符(*指针变量名)[长度n]其中“类型说明符”为所指数组的数据类型。
“*”表示其后的变量是指针类型。
“长度n”表示二维数组分解为多个一维数组时,一维数组的长度为n,也就是二维数组的列数。
应注意“(*指针变量名)”两边的括号不可少,如缺少括号则表示是指针数组(本章后面介绍),意义就完全不同了。
int(*p)[4];
/*定义指向二维数组的指针变量p,则p可以指向列数为4的二维数组*/
p=a;
/*p指向数组的首地址,则在使用a的地方可以用p代替*/
3;
i++)
for(j=0;
j<
4;
j++)printf("
%2d"
*(*(p+i)+j));
七、指向字符(串)的指针变量
字符指针的定义:
字符指针可指向一个字符,也可以指向一个字符串;
如:
charc,*p=&
c;
表示p是一个指向字符变量c的指针变量。
而:
char*s="
则表示s是一个指向字符串的指针变量。
把字符串的首地址赋予s。
请看下面一例。
char*ps="
thisisabook"
intn=10;
%s\n"
ps);
ps=ps+n;
八、指针变量作为函数参数
(一)指向变量的指针变量作为函数参数
double_num(int*num)
{
*num=*num*2;
main()
{inti=5;
double_num(&
i);
i);
}/*运行结果为10*/
double_num(intnum)
num=num*2;
double_num(i);
}/*运行结果为2*/
为何运行结果不一样?
当指针变量作为函数参数时,实际参数与形式参数指向同一地址空间,因此,当形式参数被修改时,实际参数也被修改,这种函数调用称为传址调用。
而一般的变量作为函数参数,在进行函数调用时,先为形式参数分配存储空间,在把对应的实际参数的值赋给形式参数,形式参数与实际参数代表不同的内存空间,因此,当形式参数被修改时,不会影响实际参数的值,这种函数调用称为传值调用。
(二)字符串指针作为函数参数
cpystr(char*pss,char*pds){
while((*pds=*pss)!
='
\0'
pds++;
pss++;
}
char*pa="
CHINA"
b[10],*pb;
pb=b;
cpystr(pa,pb);
stringa=%s\nstringb=%s\n"
pa,pb);
}
以数组的方式实现以上字符串复制:
cpystr(charpss[],charpds[]){
inti;
while((pds[i]=pss[i])!
i++;
二者区别:
指针变量是一个变量,可以进行自加运算,而数组名是一个常量,不能该变,在用数组名访问数组元素时,必须引用一个下标变量,相比而言要更麻烦。
[板书]
[幻灯片]
[引导]
学生对指针的思考
[重点]
[课堂设计]
[提问]
可再给出一个利用指针解决问题的题目,供学生进行课堂练习。
重点强调数组指针使用中应注意的问题
【结语】
本章主要讲述指针的相关知识。
指针是存储特定类型数据的地址。
指针依据其所指向的对象的不同,可以分为指向变量的指针、指向数组的指针、指向字符串的指针、指向结构体的指针、指向函数的指针等。
指针变量作为函数参数,传递的是地址;
数组名作为函数参数,传递的也是地址,但是数组名是常量,而指针是变量。
【思考与练习】
书278习题10.4、10.8、10.17、10.18
练习册
小结
[幻灯片]展示本课程各章节名称。
让学生了解本课程内容框架,做到心里有数。
[作业]布置课外作业,下次上课交。
八、课后小结
通过教学实践,本讲内容是全课程的重点及难点,学生的学习还需在不断的上机实践中进一步练习。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第十 指针 学时 教学 目的 要求 章节 语言程序设计 中的