第九讲 指 针 2.docx
- 文档编号:30627293
- 上传时间:2023-08-18
- 格式:DOCX
- 页数:23
- 大小:33.21KB
第九讲 指 针 2.docx
《第九讲 指 针 2.docx》由会员分享,可在线阅读,更多相关《第九讲 指 针 2.docx(23页珍藏版)》请在冰豆网上搜索。
第九讲指针2
第九章指针
本章要点:
1.掌握指针与指针变量的概念;
2.掌握指针的定义;
3.掌握指针的运算;
4.掌握指向基本类型、数组、字符串、结构体的指针变量,了解函数指针变量;
5.掌握main()函数的命令行参数。
9.1指针概念
变量地址:
变量一定占用一个数据的存储空间,该存储空间的首地址称变量地址。
指针:
一个变量的地址称为该变量的指针。
指针变量:
若一个变量专用于存放另一个变量的地址(指针),则该变量称为指针变量。
若指针变量p的值等于变量x的地址,则说指针变量p指向变量x
直接访问:
按变量地址存取变量值的方式。
间接访问:
将变量i的地址存放在另一内存单元中。
如定义i_pointer为指针变量,i_pointer=&i;
(1)先找到存放i的地址的单元地址(3010,3011);
(2)取出i的地址(2000);
(3)到2000,2001中取出i的值3
9.2变量的指针和指向变量的
指针变量
9.2.1指针变量的定义
指针变量定义的形式:
类型标识符*标识符
例如:
float*pointer_x;
int*pointer_i;
作用:
定义某些变量为指针类型,使之专门用于存放地址。
注意:
(1)*用于定义指针变量,但指针变量名不带*
如int*point_i;
定义的指针变量为point_i,不是*point_i
(2)一个指针变量只能指向同一类型的变量
如int*point_i;
point_i只能用于指向整型变量。
9.2.2指针变量的引用
(1)取地址运算符&
(2)指针运算符*(取内容)
如:
若有变量定义:
inta,*pa;
a为变量;&a就是a的地址;
pa为指针变量;*pa就是pa指向的变量;
若pa=&a,则*pa实际就是a。
例如
main()
{inta,b;
int*pa,*pb;
a=100;b=10;
pa=&a;
pb=&b;
printf(“%d,%d\n”,a,b);
printf(“%d,%d\n”,*pa,*pb);
}
对*及&的说明:
(同级运算,由右向左)
例:
将两个整型数a,b按由大到小次序输出。
main()
{int*p1,*p2,*p,a,b;
scanf(“%d,%d”,&a,&b);
p1=&a;p2=&b;
if(a
{p=p1;p1=p2;p2=p;}
printf(“a=%d,b=%d\n”,a,b);
printf(“larger=%d,little=%d\n”,*p1,*p2);
}
注意:
a和b并未交换,但p1和p2的值交换了
9.2.3指针变量作函数参数
作用:
将一个变量的地址传至另外一个函数中。
swap(p1,p2)
int*p1,*p2;
{intp;
p=*p1;
*p1=*p2;
*p2=p;
}
交换指针所指
向的变量值
main()
{inta,b;
int*pa,*pb;
scanf(“%d,%d”,&a,&b);
pa=&a;pb=&b;
if(a
printf(“%d,%d\n”,a,b);
}
运行情况:
5,9
9,5
函数调用过程如下图所示:
调用swap函数之前:
开始调用swap函数,实参pa、pb分别向形式参数p1、p2传递数据
执行函数语句,p1、p2所指向的变量的值相互交换
函数调用结束后,p1、p2所占用的内存单元被释放,
函数调用结束后,p1、p2所占用的内存单元被释放,
swap(x,y)
intx,y;
{intt;
t=x;
x=y;
y=t;
}
main()
{inta,b;
scanf(“%d,%d”,&a,&b);
if(a
printf(“%d,%d\n”,a,b);
}
形参值的改变无法传递给实参
改变指针形参的值,也不能使指针实参的值改变
swap(p1,p2)
int*p1,*p2;
{int*p;
p=p1;
p1=p2;
p2=p;
}
main()
{inta,b;
int*pa,*pb;
scanf(“%d,%d”,&a,&b);
pa=&a;pb=&b;
if(a
printf(“%d,%d\n”,*pa,*pb);
}
9.3数组的指针和指向数组的
指针变量
u数组的指针:
数组的起始地址。
u数组元素的指针:
数组元素的地址。
u数组名可视为地址常量。
指向数组元素的指针变量的定义与赋值
例如:
inta[10];
int*pa;
pa=a;(或pa=&a[0])
9.3.2通过指针引用数组元素
引用数组中的元素可以用以下方法:
下标法如a[3]
指针法即通过指向数组元素的指针找到所需的元素.这种
方法占内存少,运行速度快,因此说程序的质量高.
假设p已定义为指针变量,并已赋了一个地址,它指向某一个
数组元素.且有赋值语句p=&a[0];则:
•p+1表示数组中的下一个元素,
•a+i和p+i都是a[i]的地址,或者说它们指向a[i].
•*(a+i)或*(p+i)是a+i或p+i所指向的数组元素。
•指向数组的指针变量也可带有下标,如p[i]与*(p+i)等价。
例:
输出数组全部元素
u下标法:
main()
{inta[10],i;
for(i=0;i<10;i++)
scanf(“%d”,&a[i]);
printf(“\n”);
for(i=0;i<10;i++)
printf(“%5d”,a[i]);
}
u通过数组名计算数组元素地址,找出数组元素
for(i=0;i<10;i++)
printf(“%5d”,*(a+i));
u用指针变量指向数组元素
for(p=a;p<(a+10);p++)
printf(“%5d”,*p);
例:
用指针处理数据。
#include“stdio.h”
main()
{inta[10],*pa,i;
for(i=0;i<10;i++)
a[i]=i+1;
pa=a;
for(i=0;i<10;i++,pa++)
printf(“%d”,*pa);
printf(“\n”);}
例:
给定10个整数,求最大值。
#include“stdio.h”
#defineN10
main()
{inta[N]={5,7,3,6,2,1,8,9,4,0};
inti,*p,max;
p=a;
max=*p++;
for(i=1;i if(*p>max)max=*p; printf(“max=%d\n“,max); } 数组名作为函数参数 当用数组名作为参数时,如果形参数组中个元素的值发生 变化,实参数组元素的值也随之变化,为什么? 若有一个实参数组,想在函数中改变此数组的元素的值,实参与形参的对应关系有以下4种情况: •形参与实参都用数组名 •实参用数组名,形参用指针变量 •实参形参均用指针变量 •实参为指针变量,形参为数组名 例如: 用选择法对10个整数排序 main() {int*p,i,a[10]; voidsort(); p=a; for(i=0;i<10;i++) scanf(“%d”,p++); p=a; sort(p,10); for(p=a,i=0;i<10;i++) printf(“%d”,*p++); } voidsort(x,n) intx[],n; {inti,j,t; for(i=0;i {for(j=i+1;j if(x[i]>x[j]) {t=x[i]; x[i]=x[j]; x[j]=t;} } } 9.3.4指向多维数组的指针和指针变量 一、多维数组的地址 假设数组名为a,起始地址设为200 Statica[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};则: ua代表整个二维数组的首地址,即第0行的首地址 ua+1是数组a第1行首地址(208) ua[0],a[1],a[2]是二维数组中三个一维数组的名字(地址),是第0行,第1行,第2行的首地址,即: a[0]=a+0、a[1]=a+1、a[2]=a+2 ua[i]+j是第i行j列的地址 u*(a[i]+j)是该地址存储的值, 即a[i][j] 考虑*(a[2]+3)=? 注意: ua[i]和*(a+i)无条件等价 ua+i、a[i]、*(a+i)、&a[i][0]均表示第i行首地址; u&a[i][j]、a[i]+j、*(a+i)+j都是第i行j列元素的地址; ua[i][j]、*(a[i]+j)、*(*(a+i)+j)都是第i行j列元素的值; 二、指向数组的指针变量 定义格式: 类型说明符(*变量名)[常量表达式] 功能: 定义一个名为“变量名”的指针变量,这个指针变量所指的对象是一个有“常量表达式”个元素的一维数组 例如: 若有int(*pa)[4]; 则: 被定义成一个指针变量,它所指对象是一个有4个整型元素的数组 例如: 输出二维数组任一行任一列元素的值 main() {inta[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}; int(*p)[4],i,j; p=a; scanf(“%d%d”,&i,&j); printf(“a[%d][%d]=%d\n”,i,j,*(*(p+i)+j)); } 例如: 有一个班,3个学生,各学4门课,计算总平均分,以及第n个学生的成绩 voidaverage(p,n) float*p;intn; {floatsum=0,aver; for(;p sum=sum+(*p); aver=sum/n; printf(“average=%6.2f\n”,aver); } voidsearch(p,n) float(*p)[4];intn; {inti; printf(“thescoreofNo.%dare: \n”,n); for(i=0;i<4;i++) printf(“%6.2f“,*(*(p+n)+i));} main() {floatscore[3][4]={{65,67,70,80},{80,90,78,91}, {70,79,75,89}}; average(score,12); search(score,2); } 字符串的指针和指向字符串的指针变量 9.4.1字符串的表示形式 1用字符数组表示,如: mian() {staticcharstring[]=“IloveChina! ”; printf(“%s\n”,string); } 2用字符指针实现,如: mian() {char*string=“IloveChina! ”; printf(“%s\n”,string); } 请编写函数intfun(char*str),它的功能是判别 字符串str是否是"回文",若是,返回1,否则返回0. 例如,“13531”,“helleh”是回文,但“1353”,“Helleh”不 是回文. #include"stdio.h" intflag=0; intfun(char*str) {intn=0,k; char*p1=str; flag=0; while(*p1){n++;p1++;} for(k=0;k if(*(str+k)==*(str+n-k)flag=1; returnflag;} voidmain() {chars[128]; printf("\nPleadeenterstring: \n"); gets(s); fun(s); } 字符指针使用中的几点事项: 1.要注意一些常用的符号。 如串的结束符是‘\0’ 它的数值为0;回车符的数值为13;换行符 的值为10;文件结束符的数值为27; 2.字符指针常用于文件操作。 3.前面讲过的指针使用中要注意的问题同样适用 于字符指针。 字符指针变量与字符数组的比较: u字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是字符串的首地址。 u赋值方式: 对数组的赋值方法有: charstr[]=“Iamaboy! ” 或: charstr[20]; scanf(“%s”,str); 对字符指针变量的赋值方法有三种: (1)char*pa=“Iamaboy! ” (2)char*pa; pa=“Iamaboy! ” (3)char*pa,str[20]; pa=str; scanf(“%s”,pa); 函数的指针和指向函数的指针变量 9.5.1用函数指针变量调用函数 可以用指针变量指向一个函数。 一个函数在编译时被分配一个入口地址,这个入口地址称为函数的指针。 例: 求a和b中的大者。 main() {intmax(); int(*p)(); inta,b,c; p=max; scanf(%d,%d”,&a,&b); c=(*p)(a,b); printf(“a=%d,b=%d,max=%d”,a,b,c); } 说明: 1.指向函数的指针变量的一般定义形式是: 数据类型标识符(*指针变量名)(); 2.函数的调用可以通过函数名调用,也可以通过函数指针调用; 3.在一个程序中,一个指针变量可以先后指向不同的函数; 例如: int(*p)(); intmax(); intmin(); p=max;c=(*p)(a,b); ······ p=min;c=(*p)(a,b); 4.在给函数指针变量赋值时,只需给出函数名而不必给出参数; 5.用函数指针变量调用函数时,只需将(*p)代替函数名即可(p为指针变量名),(*p)后的括号中应加相应实参。 把指向函数的指针变量作函数参数 指向函数的指针变量可以也作为参数,以便实现函数地址的传递,即将函数名传给形参。 实参函数名f1f2 sub(x1,x2) int(*x1)(),(*x2)(); {inta,b,i,j; a=(*x1)(i); b=(*x2)(i,j); … } 返回指针值的函数 即可带回指针值的函数,其一般定义形式为: 类型标识符*函数名(参数表); 如int*a(x,y); u例如: 有若干学生的成绩(每人四门),要求输入序号后,能输出该生全部成绩。 main() {floatscore[][4]={{60,70,80,90},{57,89,46,78},{43,90,87,67}}; float*search(); float*p; inti,m; printf(“enterthenumberofstudent: ”); scanf(“%d”,&m); printf(“ThescoresofNo.%dare: \n”,m); p=search(score,m); for(i=0;i<4;i++)printf(“%5.2f\t”,*(p+i)); }(continued) float*search(pointer,n) float(*pointer)[4]; intn; {float*pt; pt=*(pointer+n); return(pt); } 运行情况: enterthenumberofstudent: 1 ThescoresofNo.1are: 57.00,89.00,46.00,78.00 9.7指针数组和指向指针的指针 9.7.1指针数组 指针数组: 由相同类型的指针变量排列而成的有序集合(每个元素都是指针变量)。 说明格式: 类型说明符*指针数组名[元素个数] 如int*p[5]注意与int(*p)[5]不同 一般用于指向若干个字符串,使字符处理更方便。 例如: #include“stdio.h” main() {char*s[4]={“dog”,“cat”,“pig”,“allanimal”}; inti; for(i=0;i<4;i++) printf(“%s\n”,*(s+i)); } 指向指针的指针(二级指针) u指向指针的指针: 指向指针数据的指针变量。 通常用于指向字符型指针变量。 u说明格式: 类型说明符**指针变量名 例如: char**p; 其含义是定义指针变量p,用于存储另一个指针变量的地址。 例如: mian() {char*s[]={“China”,“Japan”,“English”,”Franch”}; char**p; inti; p=s+2; printf(“%s\n”,*p); } 9.7.3main()函数的命令行参数 通常,main函数首行为main(),其实可带参数,如: main(argc,argv) intargc; char*argv[]; {……… } main函数的实参是和命令一同给出的,即在一个命令行中包括命令名和需要传给main函数的参数 命令行的一般形式为: 命令名参数1参数2…...参数n 假设目标文件名为“F”,需向函数传递的参数为字符串“X”和“Y”,则命令行可写为: FXY 命令行及命令行参数提 供了C程序与操作系统 间的接口 若有一个函数,其所在文件名为“F”: main(argc,argv) intargc; char*argv[]; {while(argc>1) {++argv; printf(“%s\n”,*argv); --argc;} } 若输入的命令行参数为 FABCDEF 则执行结果为 ABC DEF 有关指针的数据类型和指针运算小节 (一)有关指针的数据类型 uinti;……….定义整型变量i; uint*p;……..p为指向整型数据的指针变量; uinta[n];……定义整型数组a,它有n个元素; uint*p[n];…..定义指针数组p,它由n个指向整型数据指针元素组成; uint(*p)[n];…定义指向含n个元素的一维数组的指针变量p; uintf();……..f为带回整型函数值的函数; uint*p();…p为带回一个指针的函数,该指针指向整型数据; uint(*p)();….p为指向函数的指针,该函数返回一个整型值; uint**p;…….p是一个指针变量,它指向一个指向整型数据的指针变量。 (二)指针运算小结 1.赋值= 语法: 指针变量=指针表达式 若有变量定义: int*p1,*p2,a,array[10]; up1=&a;………….变量的地址。 up2=array;…………数组的首地址。 up2=&array[i];…….数组第i个元素的地址。 up1=p2;…………..一个指针变量值赋给另一个指针变量。 2.取地址运算& 语法: &变量 设有变量说明inta,b,*p,*q; p=&a;把a的地址赋给p,即让p指向a q=p;让q也指向a,现在p、q都指向a p=&b;让p也指向b,现在q指向a,p指向b 其中&a表示a的地址值 语法: *指针表达式 设p是一个指针表达式,则: (1)若*p出现在赋值号左边,表示给p所指变量赋值 (2)若*p不出现在赋值号左边,表示p所指变量的值 若有变量说明: inta,*p;则: p=&a;让p指向变量a *p=10;*p出现在赋值号左边,等价于a=10 printf(“%d”,*p);*p不出现在赋值号左边,打印p所指变量的值 scanf(“%d”,&a);给变量a输入值 scanf(“%d”,p);同上 *p+25等价于a+25 4.指针表达式与整数相加减 形式: p+n或p-n 其中: p是任意一个指针表达式,n是任何一种整型表达式 计算规则: 表达式p+n的值=p的值+p所指类型长度*n 表达式p-n的值=p的值-p所指类型长度*n 说明: 只有当p和p+n或p-n都指向连续存放的同类型数据区域,例如数组时,指针加减才有实际意义。 C语言规定: 表达式p+n和p-n的类型与p相同。 例如: 设有变量定义: inta[10],*p,*q;则 p=ap指向a[0] q=a+6q指向a[6] p=q-4p指向a[2] 5.自增自减运算 语法: p++;p--;++p;--p; 例如: 设有变量定义: inta[]={1,2,3,4,5},*p,*q; p=q=&a[3]; *p++=100;a[? ]变成100 *++q=100;a[? ]变成100 p++与++p的区别: 表达式p++的值等于p的原来值; 表达式++p的值等于p的新值; 6.关系运算 只有同类指针进行比较才有意义 u==和! =运算符,比较的是两个指针表达式是否指向同一个内存单元; u<、<=、>、>=,比较的是两个指针所指内存区域的先后次序 u语法: 指针表达式关系运算符指针表达式 若有变量定义: inta[10];int*p=a,*q=a+3; 试判断以下表达式的值 p==&a[0]p==&a[1]p==qp+4=q+2p q>a+2p>q 可用以下语句给数组a输入10个数 for(p=a,q=a+10;p 7.同类指针相减 同类指针相减时,两个指针应该指向连续存放的同类数据区域 语法: p-q 说明: p-q的值,等于(p的值-q的值)/所指类型长度,即p,q两个指针之间数据元素的个数 例如: 若有inta[10],p,q; p=a; q=&a[5]; 则p,q
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第九讲 第九