还剩17页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
C语言基础知识指针简介指针是C语言中广泛使用的一种数据类型运用指针编程是C语言最主要的风格之一利用指针变量可以表示各种数据结构;能很方便地使用数组和字符串;并能象汇编语言一样处理内存地址,从而编出精练而高效的程序指针极大地丰富了c语言的功能学习指针是学习c语言中最重要的一环,能否正确理解和使用指针是我们是否掌握C语言的一个标志同时,指针也是C语言中最为困难的一部分在学习中除了要正确理解基本概念,还必须要多编程,上机调试只要作到这些,指针也是不难掌握的指针的基本概念在计算机中,所有的数据都是存放在存储器中的一般把存储器中的一个字节称为一个内存单元,不同的数据类型所占用的内存单元数不等,如整型量占2个单元,字符量占1个单元等,在第二章中已有详细的介绍为了正确地访问这些内存单元,必须为每个内存单元编上号根据一个内存单元的编号即可准确地找到该内存单元内存单元的编号也叫做地址既然根据内存单元的编号或地址就可以找到所需的内存单元,所以通常也把这个地址称为指针内存单元的指针和内存单元的内容是两个不同的概念可以用一个通俗的例子来说明它们之间的关系我们到银行去存取款时,银行工作人员将根据我们的帐号去找我们的存款单,找到之后在存单上写入存款、取款的金额pmaxpmin为整型指针变量输入提示输入三个数字如果第一个数字大于第二个数字…指针变量赋值指针变量赋值指针变量赋值指针变量赋值判断并赋值判断并赋值输出结果数组指针变量的说明和使用指向数组的指针变量称为数组指针变量在讨论数组指针变量的说明和使用之前,我们先明确几个关系一个数组是由连续的一块内存单元组成的数组名就是这块连续内存单元的首地址一个数组也是由各个数组元素(下标变量)组成的每个数组元素按其类型不同占有几个连续的内存单元一个数组元素的首地址也是指它所占有的几个内存单元的首地址一个指针变量既可以指向一个数组,也可以指向一个数组元素,可把数组名或第一个元素的地址赋予它如要使指针变量指向第i号元素可以把i元素的首地址赋予它或把数组名加i赋予它设有实数组a指向a的指针变量为pa从图
6.3中我们可以看出有以下关系paaa
[0]均指向同一单元,它们是数组a的首地址,也是0号元素a⑼的首地址pa+la+la[l]均指向1号元素a[l]类推可知a+ia+ia[i]指向i号元素a[i]应该说明的是pa是变量,而aa[i]都是常量在编程时应予以注意main{inta
[5]i;fori=0;ia[i]=i;printfa[%d]=%d\nia[i];printf\n;}主函数定义一个整型数组和一个整型变量循环语句给数组赋值打印每一个数组的值输出换行数组指针变量说明的一般形式为类型说明符*指针变量名其中类型说明符表示所指数组的类型从一般形式可以看出指向数组的指针变量和指向普通变量的指针变量的说明是相同的引入指针变量后,就可以用两种方法来访问数组元素了第一种方法为下标法,即用a[i]形式访问数组元素在第四章中介绍数组时都是采用这种方法第二种方法为指针法,即采用*pa+i形式,用间接访问的方法来访问数组元素main{inta
[5]J*pa;pa=a;fori=0;i*pa=i;pa++;pa=a;fori=0;iprintfa[%d]=%d\ni/*pa;pa++;主函数定义整型数组和指针将指针pa指向数组a循环将变量i的值赋给由指针pa指向的a□的数组单元将指针pa指向a□的下一个单元指针pa重新取得数组a的首地址循环用数组方式输出数组a中的所有元素将指针pa指向a□的下一个单元下面,另举一例,该例与上例本意相同,但是实现方式不同main{inta
[5]i*pa=a;fori=0;i*pa=i;printfa[%d]=%d\nJ++*pa++;主函数定义整型数组和指针,并使指针指向数组a循环将变量i的值赋给由指针pa指向的a□的数组单元用指针输出数组a中的所有元素,同时指针pa指向a口的下一个单元数组名和数组指针变量作函数参数在第五章中曾经介绍过用数组名作函数的实参和形参的问题在学习指针变量之后就更容易理解这个问题了数组名就是数组的首地址,实参向形参传送数组名实际上就是传送数组的地址,形参得到该地址后也指向同一数组这就好象同一件物品有两个彼此不同的名称一样同样,指针变量的值也是地址,数组指针变量的值即为数组的首地址,当然也可作为函数的参数使用floataverfloat*pa;main{floatsco
[5]av*sp;inti;sp=sco;printf\ninput5scores:\n;fori=0;iav=aversp;printfaveragescoreis%
5.2fMav;floataverfloat*painti;floatavs=0;fori=0;iav=s/5;returnav;指向多维数组的指针变量本小节以二维数组为例介绍多维数组的指针变量
一、多维数组地址的表示方法设有整型二维数组凯3]⑷如下01234567891011设数组a的首地址为1000各下标变量的首地址及其值如图所示在第四章中介绍过,C语言允许把一个二维数组分解为多个一维数组来处理因此数组a可分解为三个一维数组,即a
[0]a[l]a
[2]o每一个一维数组又含有四个元素例如a⑼数组,含有a
[0]
[0]a[O][l]a
[0]
[2]a
[0]⑶四个元素数组及数组元素的地址表示如下a是二维数组名,也是二维数组0行的首地址,等于1000a
[0]是第一个一维数组的数组名和首地址,因此也为1000*a+0或*a是与a⑼等效的,它表示一维数组a
[0]0号元素的首地址也为1000a
[0]⑼是二维数组a的0行0列元素首地址,同样是1000o因此aa
[0]*a+0匕amp;a
[0]⑼是相等的同理,a+1是二维数组1行的首地址,等于1008oa⑴是第二个一维数组的数组名和首地址,因此也为1008凯1]⑼是二维数组a的1行0列元素地址,也是1008o因此是等同的由此可得出:a+ia[i]*a+ia[i]
[0]是等同的此外,a[i]和a[i]也是等同的因为在二维数组中不能把a[i]理解为元素a[i]的地址,不存在元素a[i]C语言规定,它是一种地址计算方法,表示数组a第i行首地址由此,我们得出a[i]a[i]*a+i和a+i也都是等同的另外,a⑼也可以看成是a
[0]+0是一维数组矶0]的0号元素的首地址,而a
[0]+l则是a⑼的1号元素首地址由此可得出a[i]+j则是一维数组a[i]的j号元素首地址,它等于由a[i]=*a+i得a[i]+j=*a+i+j由于*a+i+j是二维数组a的i行j列元素的首地址该元素的值等于**a+i+jo[Explain]#definePF%d%d%d%d%d\rrstaticinta
[3]
[4]={01234567891011;printfPFa*aa
[0]a[0La
[0]
[0];printfPFa+L*a+la[lLa[l]a[l][O];printfPFa+2*a+2a
[2]a
[2]a⑵
[0];printf%d%d\rTa[l]+l*a+l+l;printf%d/%d\n*a[l]+l**a+l+l;}
二、多维数组的指针变量把二维数组a分解为一维数组a⑼⑵之后,设p为指向二维数组的指针变量可定义为int*p
[4]它表示p是一个指针变量,它指向二维数组a或指向第一个一维数组a
[0]其值等于aa
[0]或a
[0]⑼等而p+i则指向一维数组媒i]从前面的分析可得出*p+i+j是二维数组i行j列的元素的地址,而**p+i+j则是i行j列元素的值二维数组指针变量说明的一般形式为类型说明符*指针变量名[长度]其中“类型说明符〃为所指数组的数据类型〃*〃表示其后的变量是指针类型长度〃表示二维数组分解为多个一维数组时,一维数组的长度,也就是二维数组的列数应注意*指针变量名〃两边的括号不可少,如缺少括号则表示是指针数组本章后面介绍,意义就完全不同了[Explain]main{staticinta
[3]
[4]={0l23456789」0ll};intij;P=a;fori=0;iforj=0;jExpain字符串指针变量的说明和使用字符串指针变量的定义说明与指向字符变量的指针变量说明是相同的只能按对指针变量的赋值不同来区别对指向字符变量的指针变量应赋予该字符变量的地址如chare*p=c;表示p是一个指向字符变量c的指针变量而char*s=CLanguage;则表示s是一个指向字符串的指针变量把字符串的首地址赋予s请看下面一例main{char*ps;ps=CLanguageM;printf%slps;}运行结果为CLanguage上例中,首先定义PS是一个字符指针变量,然后把字符串的首地址赋予ps应写出整个字符串,以便编译系统把该串装入连续的一块内存单元,并把首地址送入ps程序中的char*ps;ps=CLanguage”;等效于:char^ps^CLanguage”;输出字符串中n个字符后的所有字符main{char*ps=thisisabook;intn=10;ps=ps+n;printf%s\nps;}运行结果为book在程序中对ps初始化时,即把字符串首地址赋予ps当ps=ps+10之后,ps指向字符“b〃因此输出为”bookmain{charst
[20]/ps;inti;printfinputastring:\n;ps=st;scanf%sps;fori=0;ps[i]!=\0;i++ifps[i]==k{printfthereisakinthestring\n;break;在这里,帐号就是存单的指针,存款数是存单的内容对于一个内存单元来说单元的地址即为指针,其中存放的数据才是该单元的内容在C语言中,允许用一个变量来存放指针,这种变量称为指针变量因此,一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针图中,设有字符变量C其内容为伙〃(ASCII码为十进制数75)C占用了011A号单元(地址用十六进数表示)设有指针变量P内容为011A这种情况我们称为P指向变量C或说P是指向变量C的指针严格地说,一个指针是一个地址,是一个常量而一个指针变量却可以被赋予不同的指针值,是变o但在常把指针变量简称为指针为了避免混淆,我们中约定“指针〃是指地址,是常量,“指针变量〃是指取值为地址的变量定义指针的目的是为了通过指针去访问内存单元既然指针变量的值是一个地址,那么这个地址不仅可以是变量的地址,也可以是其它数据结构的地址在一个指针变量中存放一个数组或一个函数的首地址有何意义呢因为数组或函数都是连续存放的通过访问指针变量取得了数组或函数的首地址,也就找到了该数组或函数这样一来,凡是出现数组,函数的地方都可以用一个指针变量来表示,只要该指针变量中赋予数组或函数的首地址即可这样做,将会使程序的概念十分清楚,程序本身也精练,高效在C语言中,一种数据类型或数据结构往往都占有一组连续的内存单元用“地址〃这个概念并不能很好地描述一种数据类型或数据结构,而〃指针〃虽然实际上也是一个地址,但它却是一个数据结构的首地址,ifps[i]==\0printflThereisnokinthestring\nM;它是〃指向〃一个数据结构的,因而概念更为清楚,表示更为明确这也是引入〃指针〃概念的一个重要原因指针变量的类型说明对指针变量的类型说明包括三个内容⑴指针类型说明,即定义变量为一个指针变量;⑵指针变量名;⑶变量值(指针)所指向的变量的数据类型其一般形式为类型说明符*变量名;其中,*表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型例如int*pl;表示pl是一个指针变量,它的值是某个整型变量的地址或者说pl指向一个整型变量至于pl究竟指向哪一个整型变量,应由向pl赋予的地址来决定再如staicint*p2;float*p3;char*p4;应该注意的是,一个指针变量只能指向同类型的变量,如P3只能指向浮点变量,不能时而指向一个浮点变量,时而又指向一个字符变量指针变量的赋值指针变量同普通变量一样,使用之前不仅要定义说明,而且必须赋予具体的值未经赋值的指针变量不能使用,否则将造成系统混乱甚至死机指针变量的赋值只能赋予地址,决不能赋予任何其它数据否则将引起错误在C语言中,变量的地址是由编译系统分配的,对用户完全透明,用户不知道变量的具体地址C语言中提供了地址运算符来表示变量的地址其一般形式为变量名;如a变示变量a的地址,b表示变量b的地址变量本身必须预先说明设有指向整型变量的指针变量p如要把整型变量a的地址赋予p可以有以下两种方式⑴指针变量初始化的方法inta;int*p=a;⑵赋值语句的方法inta;int*p;P=a;不允许把一个数赋予指针变量,故下面的赋值是错误的int*p;p=1000;被赋值的指针变量前不能再加*〃说明符,如写为*p=a也是错误的指针变量的运算指针变量可以进行某些运算,但其运算的种类是有限的它只能进行赋值运算和部分算术运算及关系运算.指针运算符⑴取地址运算符取地址运算符是单目运算符,其结合性为自右至左,其功能是取变量的地址在scanf函数及前面介绍指针变量赋值中,我们已经了解并使用了运算符⑵取内容运算符*取内容运算符*是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量在*运算符之后跟的变量必须是指针变量需要注意的是指针运算符*和指针变量说明中的指针说明符*不是一回事在指针变量说明中,*〃是类型说明符,表示其后的变量是指针类型而表达式中出现的“*〃则是一个运算符用以表示指针变量所指的变量main{inta=5*p=a;printf%cT*p;}表示指针变量p取得了整型变量a的地址本语句表示输出变量a的值.指针变量的运算⑴赋值运算指针变量的赋值运算有以下几种形式
①指针变量初始化赋值,前面已作介绍
②把一个变量的地址赋予指向相同数据类型的指针变量例如inta/pa;pa=a;
③把一个指针变量的值赋予指向相同类型变量的另一个指针变量如inta*pa=a*pb;pb=pa;由于pazpb均为指向整型变量的指针变量,因此可以相互赋值
④把数组的首地址赋予指向数组的指针变量例如inta
[5]*pa;pa=a;数组名表示数组的首地址,故可赋予指向数组的指针变量pa也可写为pa=a[O];当然也可采取初始化赋值的方法inta
[5]*pa=a;
⑤把字符串的首地址赋予指向字符类型的指针变量例如chai^pqpcdclanguage”;或用初始化赋值的方法写为chai^pcdCLanguage”;这里应说明的是并不是把整个字符串装入指针变量,而是把存放该字符串的字符数组的首地址装入指针变量在后面还将详细介绍
⑥把函数的入口地址赋予指向函数的指针变量例如int*pf;pf=f;2加减算术运算对于指向数组的指针变量,可以加上或减去一个整数设pa是指向数组a的指针变量,则pa+npa-n/pa++/++papa-7-pa运算都是合法的指针变量加或减一个整数n的意义是把指针指向的当前位置(指向某数组元素)向前或向后移动n个位置应该注意,数组指针变量向前或向后移动一个位置和地址加1或减1在概念上是不同的因为数组可以有不同的类型,各种类型的数组元素所占的字节长度是不同的如指针变量加1即向后移动1个位置表示指针变量指向下一个数据元素的首地址而不是在原地址基础上加1例如inta
[5]*pa;pa=a;pa邛a+2;指针变量的加减运算只能对数组指针变量进行,对指向其它类型变量的指针变量作加减运算是毫无意义的
(3)两个指针变量之间的运算只有指向同一数组的两个指针变量之间才能进行运算,否则运算毫无意义
①两指针变量相减两指针变量相减所得之差是两个指针所指数组元素之间相差的元素个数实际上是两个指针值(地址)相减之差再除以该数组元素的长度(字节数)例如pfl和pf2是指向同一浮点数组的两个指针变量,设pfl的值为2010Hpf2的值为2000H而浮点数组每个元素占4个字节,所以pfl-pf2的结果为(2000H-2010H)/4=4表示pfl和pf2之间相差4个元素两个指针变量不能进行加法运算例如,pfl+pf2是什么意思呢毫无实际意义
②两指针变量进行关系运算指向同一数组的两指针变量进行关系运算可表示它们所指数组元素之间的关系例如pfl==pf2表示pfl和pf2指向同一数组元素pflpf2表示pfl处于高地址位置pflmain{inta=10b=20/s/t*pa*pb;pa=a;pb=b;s=*pa+*pb;t=*pa**pb;printfla=%d\nb=%d\na+b=%d\na*b=%d\nlaba+ba*b;printfs=%d\nt=%d\nst;}说明papb为整型指针变量给指针变量pa赋值,pa指向变量a给指针变量pb赋值,pb指向变量b本行的意义是求a+b之和,*pa就是a*pb就是b本行是求a*b之积输出结果输出结果指针变量还可以与0比较设P为指针变量,则p==o表明p是空指针,它不指向任何变量;p!=0表示p不是空指针空指针是由对指针变量赋予0值而得到的例如#defineNULLOint*p二NULL;对指针变量赋0值和不赋值是不同的指针变量未赋值时,可以是任意值,是不能使用的否则将造成意外错误而指针变量赋0值后,则可以使用,只是它不指向具体的变量而已main{intabc*pmax*pmin;printfinputthreenumbers:\n1;scanf%d%d%dabc;ifab{pmax=a;pmin=b;}else{pmax=b;pmin=a;}ifc*pmaxpmax=c;ifcprintfmax=%d\nmin=%d\n*pmax*pmin;。