版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第3章指针本章主要内容指针概念指针的运算指针与数组指针变量作为函数参数返回指针值的函数(指针函数)指向函数的指针main函数的参数指向指针的指针带着疑问学习这个指针的类型是什么?指针所指的数据类型是什么?该指针指向了哪里(指针的值、指针指向的内存区)?指针本身所占据的内存区3.1指针概念1、内存与地址
☆内存中的每个位置由一个独一无二的地址标识
☆内存中的每个位置都包含一个值
☆地址与内容(eg.)0x000000000x000000010x000000100x00000011……0xFFFFFFFC0xFFFFFFFD0xFFFFFFFE0xFFFFFFFF2、值与类型(eg.)3、变量的指针和指针变量
变量的指针就是变量的地址,指针变量的值就是该指针变量所指变量的内存首地址
*p就表示指针变量p所指向的变量(取值)指针概念4、间接访问指针概念112-13.14100108
inta=112,b=-1; floatc=3.14; int*d=&a;//int*d;d=&a; float*e=&c;//int*e;e=&c;100104108112116abcde可以通过*d,*e来操作a与c变量5、指针变量的定义[存储类型]数据类型*指针变量名[=初始值];
eg:inti,j;
int*p1,*p2; p1=&i; p2=&j;
画图说明指针概念说明:指针变量所指向的类型可以是整、实、字符型等。
指针变量只能指向同一类型的变量。
指针变量是p1、p2,而不是*p1、*p2。*p1和*p2是p1和p2所指向的变量i和j。
指针变量中只能存放地址。
p1=100;*p1=&i;非法指针概念6、未初始化和非法指针
eg:int*a;*a=12;
question1:指针a指向哪里?
question2:万一a存放的是合法地址呢?7、NULL指针指针概念8、指针、间接访问和左值
eg:inta; int*d=&a; *d=10-*d;
d=10-*d;9、指针、间接访问和变量
eg:*&a=25; *100=25;
*(int*)100=25;//指针常量指针概念10、指针变量的引用 运算符:取地址--&
取内容--*(地址运算符)
(1)指针变量p的内容为地址量;*p为指针p的目标量,内容为数据,即指针变量p所指向的变量的值。 (2)*p=i;是将变量i的值赋给目标变量*p
(3)p=&i;是将变量i的地址赋给指针变量p。 (4)&p为指针变量p的地址。 (5)&(*p)的结果为p,即变量*p的地址。 (6)*(&i)的结果就是i本身。指针概念右图中:P==2000*p==3&p==3010&(*p)==2000*(&i)==3指针概念例3.1main(){ inta,b;int*p1,*p2;a=100;b=10;p1=&a;p2=&b;/
将变量a和b的地址赋给指针变量p1和p2/printf(“%d,%d\n”,a,b);printf(“%d,%d\n”,*p1,*p2);/*p1和*p2就是变量a和b/}运行结果:100,10100,10指针概念注意:本题中a和b并未交换,而p1和p2的值改变。例3.2
main()
{int*p1,*p2,*p,a,b;
scanf(“%d,%d”,&a,&b);
p1=&a;p2=&b;
if(a<b){p=p1;p1=p2;p2=p;}
printf(“a=%d,b=%d\n”,a,b);printf(“max=%d,min=%d\n”,*p1,*p2);
}运行情况:
5,9
a=5,b=9
max=9,min=5指针概念3.2指针的运算3.2.1指针的算术运算
++/--+/-
分析*p++与(*p)++3.2.2指针的关系运算
==/!=3.3指针与数组1、指向一维数组的指针例:inta[10],*p;p=&a[0];//将a[0]元素的地址赋给指针 //变量p
在C中,数组名代表数组的首地址。因此,p=a;p=&a[0];注:p=a;//将a数组的首地址赋给指针变量p //这里的a并不代表整个数组。
通过指针引用数组元素
p
=
a
;/*将整型数组a的首地址赋给指针变量
p*/
*p=5;/*将5赋给a数组的第一个元素a[0],等价于
a[0]=5*/
p+1表示:指针变量p当前所指的数组元素的下一个元素,不是p的值加
1
。若有p=&a[0],则
p+i
(或a+i)就是
a[i]
的地址(因为a代表数组a的首地址)。若有p=&a[0],则*(p+i)或*(a+i)就是p+i或a+i所指向的数组元素,即a[i]。即:*(p+i)=*(a+i)=a[i]。
指向数组的指针变量可以带下标,如:
p[i]
*(p+i)指向一维数组的指针也可写成如下:main(){inta[10],*p=a
,i
;for(
i=0;i<10;i++)scanf(“%d”,p++);printf(“\n”);
p=a;/
此语句必不可少
/for(
i=0;i<10;i++,p++)printf(“%d”,*p);}例3.3输出有10个元素的整型数组a的元素值。main(){inta[10],*p,i
;for(i=0;i<10;i++)scanf(“%d”,&a[i]);printf(“\n”);for(p=a;p<(a+10);p++)printf(“%d”,*p);}指向一维数组的指针
如果p指向数组a
(即p=a),则:p++(或p+=1)表示p指向下一个元素;*p表示取得当前所指元素之值。*p++
*(p++)a[i++]
表示先求*p,再p+1p(*p--类似)*(++p)a[++i],表示p+1p,再求*p。(*p)++a[i]+1。
注意指向数组的指针变量的当前值,因为指针可以指向数组最后一个元素以后的内存单元。指向一维数组的指针
staticinta[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};说明:
行地址
a
:代表整个二维数组的首地址,也是第0行的首地 址,值为&a[0][0]。
a+2:代表第2行的首地址,值为&a[2][0]
列地址
a[0]
*(a+0)&a[0][0]:代表0行0列的首地址
a[1]
*(a+1)&a[1][0]:代表1行0列的首地址
a[0]+1
*(a+0)+1&a[0][1]a[1]+2
*(a+1)+2&a[1][2]。
*(a+1)+2不能写成*(a+1+2),否则就变成*(a+3),即a[3]。2、指向多维数组的指针因为a[0]+1
*(a+0)+1&a[0][1]
所以*(a[0]+1)
*(*(a+0)+1)a[0][1]
同理,*(*(a+0)+1)
*(*a+1)a[0][1],*(a[
i
]+j)
*(*(a+i)+j)a[
i
][j]一维数组a[i]:代表第i+1个元素所占的内存单元。二维数组a[i]:代表一维数组名,a[i]本身不占用内存单元,只是一个地址务必记住:*(a+i)a[i]地址:a、a+i、a[
i
]、*(a+i)、*(a+i)+j、a[
i
]+j值:*(a[
i
]+j)
*(*(a+i)+j)a[
i
][j]。staticinta[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}在一维数组中:a+i指第i个数组元素的存储单元;在二维数组中:a+i=a[i]=*(a+i)=&a[i]=&a[i][0],都表示i行0列元素的地址值。在二维数组中&a[i]并不是a[i]单元的物理地址,但能得到i行的首地址。例3.4输出二维数组中的任一元素。main(){
staticinta[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};int(*p)[4],i,j;p=a;scanf(“i=%d,j=%d”,&i,&j
);printf(“a[%d,%d]=%d\n”,i,j,*(*(p+i)+j));}运行情况:i=1,j=2/*
注意这里的输入格式*/a[1,2]=13程序中的“int(*p)[4]”表示
p
是一个指向包含4个元素的一维数组的指针变量,即p是一个行指针,指向一维数组的首地址。由于运算符优先级的关系,这里的(*p)[4]不能写成*p[4]。一、字符串的表示形式
用字符数组实现
staticcharstr[]=“IloveChina!”;str[i]表示字符数组中的第i+1个字符。如:str[8]为字符‘h’
用字符指针实现
char*a=“IloveChina!”;
尽管没有定义为字符数组,但实际在内存开辟了一个字符数组用来存放字符串常量。同样,a[8]为字符‘h’。注意:
a不是字符串变量,此处将“IloveChina!”的首地址赋给指针变量a。3、字符串的指针二、字符串指针作函数参数
可以用地址传递的方式,即用字符数组名作参数或用指向字符串的指针变量作参数,将一个字符串从一个函数传递到另一个函数。例3.5用函数调用实现字符串的复制。
用字符数组作参数voidcopy_string(charfrom[],charto[]){inti=0;while(from[i]!=‘\0’){to[i]=from[i];i++;}to[i]=‘\0’;}main(){chara[]=“Iamateacher.”;charb[]=“youarestudents.”;copy_string(a,b);printf(“string_a=%s\nstring_b=%s\n”,a,b);}运行结果:string_a=Iamateacher.string_b=Iamateacher.
形参用字符指针变量voidcopy_string(char*from,char*to){for(;*from!=‘\0’;from++;to++)
*to=*from;
*to=‘\0’;}main(){
char*a=“Iamateacher.”;char*b=“youarestudents.”;copy_string(a,b);printf(“string_a=%s\nstring_b=%s\n”,a,b);}说明:字符数组:由若干个元素组成,每个元素可存放1
个字符。字符指针变量:存放的是字符串的首地址,绝不是将字符串存放到字符指针变量中。
字符数组:赋初值最好要用static存储类别如:
staticstr[]={“IloveChina!”};
字符指针变量:赋初值不必加static,如:
char*a=“IloveChina!”;
这是因为它只是对指针变量初始化,而不是对数组初始化。字符数组:只能对各个元素赋值,下列方式错误
charstr[15];str=“IloveChina!”;三、字符指针变量与字符数组
对字符指针变量赋初值时:char*a=“IloveChina!”;等价于:
char*a; a=“IloveChina!”;即数组可以在变量定义时整体赋初值,但不能在赋值语句中整体赋值。注意:对数组初始化时:
staticcharstr[14]={“IloveChina!”};不等价于:
charstr[14]; str[]=“IloveChina!”;字符指针变量:可采用char*a;a=“IloveChina!”;这里赋给a的是字符串的首地址,而不是字符串。
charstr[14]; scanf(“%s”,str);是可以的。但如果写成如下形式:
char*a; scanf(“%s”,a);
是非常危险的。因为指针变量没有确定的地址而指向程序区或其它数据区,从而会造成系统“冲突”。应写成如下形式:
char*a,str[10]; a=str; scanf(“%s”,a);
数组在编译时被分配内存单元,有确定的地址。而指针变量必须赋给一个确定的地址值,否则,在程序运行时会发生意想不到的后果。如:
main() {
char*a=“IloveChina!”; a=a+7; printf(“%s”,a); }运行结果如下:
China!下面的写法是错误的:
charstr[]={“IloveChina!”}; str=str+7; printf(“%s”,str);
若定义一个指针变量使它指向一个字符串后,可以用下标形式引用指针变量所指字符串中的字符。
指针变量的地址值可以改变,而数组名的地址值不能改变。如:例3.6main(){
char*a=“IloveChina.”;inti=5;printf(“%c\n”,a[i]);for(i=7;a[i]!=‘\0’;i++)printf(“%c”,a[i]);}运行结果如下:eChina.
可用指针变量指向一个格式字符串来代替printf函数中的格式字符串。也可以在定义字符数组赋初值时赋予一个格式字符串代替printf函数中的格式字符串。如:
char*format; format=“a=%d,b=%f\n”; printf(format,a,b);它相当于:
printf(“a=%d,b=%f\n”,a,b);例3.7顺读和倒读都一样的字符串称为“回文”,如:LEVEL。试编写一个判断输入的字符串是否为回文的程序。#include“stdio.h”#include“string.h”main(){
chars[81],*pi,*pj;inti,j,n;gets(s);n=strlen(s);pi=s;pj=s+n-1;/pi和pj分别指向字符串首末/while(*pi==‘’)pi++;/
跳过输入时的前导空格/while(*pj==‘’)pj--;/
跳过输入时的尾随空格/while((pi<pj)&&(*pi==*pj)) {pi++;pj--;}if(
pi<pj)printf(“NO\n”);elseprintf(“YES\n”);}4、指针数组char**p
;inti;for(i=0;i<5;i++){p=name+i;printf(“%s\n”,*p);}}定义形式:类型标识符*数组名[数组长度]例如:int*p[4];
定义了有4个元素的指针数组,每个数组元素都指向一个整型变量。例8.8
main()
{staticchar*name[]={“Followme”,“BASIC”,“GreatWall”, “FORTRAN”,“Computerdesign”};指向指针的指针作用:将一个变量的地址传送至另一个函数中
例3.93.4指针变量作为函数参数用指针变量作参数调用函数能获得多个值。此例中a和b的值交换,而s1和s2的值不变。3.5返回指针值的函数(指针函数)定义形式:类型标识符*函数名(参数表)
例如:int*fa(x,y);注意:指针函数VS指向函数的指针变量例:int*a(x,y);int(*a)();a为整型指针函数a为指向函数的指针变量3.6指向函数的指针一、用函数指针变量调用函数例3.10求两数中的较大者。
main(){
intmax();int(*p)();/
定义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);}max(x,y)intx,y;{
intz;if(x>y)z=x;elsez=y;return(z);}函数的参数可以是:变量指向变量的指针变量数组名指向数组的指针变量函数指针变量函数指针变量作用:将函数名传递给形参,实现函数地址的传递。
二、用函数指针变量作函数参数3.7main函数的参数形式:main(intargc,char*argv[],char*env[])参数含义如下:argc
表示命令行的参数个数。a
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 大学生职业生涯规划创业计划书模板30
- 《电气控制原理图》课件
- DB32T-建筑工程BIM规划报建数据规范编制说明
- 给予是快乐的课件公开课专用
- 《口腔洁治课件》课件
- 基因工程的基本操作程序课件
- 《TA沟通分析课程》课件
- 《伊犁河大桥》课件
- 生活处处有哲学课件
- 单位管理制度展示汇编【员工管理篇】
- 慢阻肺GOLD指南解读
- T-BIE 003-2023 通孔回流焊接技术规范
- 口腔颌面外科学 09颞下颌关节疾病
- 台达变频器说明书
- 2023年广东罗浮山旅游集团有限公司招聘笔试题库及答案解析
- DB11-T1835-2021 给水排水管道工程施工技术规程高清最新版
- 解剖篇2-1内脏系统消化呼吸生理学
- 《小学生错别字原因及对策研究(论文)》
- 智慧水库平台建设方案
- 系统性红斑狼疮-第九版内科学
- 粮食平房仓设计规范
评论
0/150
提交评论