指针、数组知识总结计算机二级C辅导.doc_第1页
指针、数组知识总结计算机二级C辅导.doc_第2页
指针、数组知识总结计算机二级C辅导.doc_第3页
指针、数组知识总结计算机二级C辅导.doc_第4页
指针、数组知识总结计算机二级C辅导.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第六章 指针一、变量的地址和指针(一)变量的地址1、内存地址:计算机的内存是以字节为单位的一片连续的存储空间,每一个字节都有一个编号,这个编号就称为地址。例如:一台计算机内存为512MB=512*1024KB=512*1024*1024B,即共有512*1024*1024个地址。(1)内存空间都是连续的,故地址编号也是连续的。(2)定义变量后自动分配相应的内存空间。例如:int a;自动分配4个字节的内存空间给变量a。(画图说明:1011、1012、1013、1014)(3)每个变量的地址是指所占存储单元的第一个字节的地址。例如:上例中变量a的地址为1011。2、直接存取方式:直接按变量的地址存取变量值的方式。例如:int a;a=5;为变量a分配内存空间,进而变量a有了对应的内存地址,将5赋值给变量a,即将5存入变量a对应的内存空间。看似对变量a赋值,实际上是对变量a对应的内存空间存放数值。3、关于地址的形象认识:打个比喻:内存好比就是一个公司的行政大楼,内存当中的每一个字节就好比是大楼中的每一个房间,每一字节内存都有编号,即内存地址,就好比是房间的门牌号。我们定义一个变量a就要为这个变量a分配内存空间,就好比是公司成立一个财务科就要为这个财务科分配房间。将5赋值给变量a就好比是要将一大摞钱送到财务科,实际上就是将钱送到财务科所在的那个房间,同理也就是将5存放到变量a对应的内存空间,而具体怎么由变量a找到其对应的内存空间,是由计算机完成的,因为a的内存空间的分配就是计算机完成的。就好比是我们要找财务科,如果不熟悉地方的话,就问公司内部人员,他会告诉你房间号,同理计算机就如同公司内部人员,它就会告诉5怎么找到变量a的内存空间,即a的地址。通过变量a对其内存空间进行存取数据的方式称为直接存取。(二)指针变量的定义1、间接存取方式:我们定义一种变量,这种变量是专门用来存放某种内存地址的。比如我们定义变量p,计算机就为它分配内存空间,就当然有地址(假如为9257)。将变量a的内存地址(1011)存放到变量p中,此时我们要访问变量a所代表的存储单元,我们可以先找到变量p的地址(9527),从中取出a的地址(1011),然后再去访问1011为首地址的存储单元。这种方式就称为“间接存取”方式。(1)一旦变量p存放了变量a的地址就称变量p指向变量a。此时变量p称为指针(地址)变量,它与变量a不同,它是用来存放指针(即地址)的变量。(2)任何类型的指针变量均占4Bytes。2、指针变量定义:类型名 *指针变量名1,*指针变量名2,;例:int *p,*q;(1)p、q为用户标识符,*为说明符,不可省略,否则就不是指针变量而为普通变量了。(2)int为类型名,说明p和q是两个指向整型变量的指针,即变量p和q只能存放int类型变量的地址。称int是指针变量p和q的“基类型”。(3)二级指针:类型名 *指针变量名1,*指针变量名2,;例:int *p;二级指针变量就是其中存放的是指针变量的地址。例如:定义一个int变量k,其内存空间为(2012、2013、2014、2015),再定义int *s;s的地址为9521,但是其指向2012,即其中存放的内容为2012,再定义二级指针:int *p;p地址为4567,它指向9521,即p对应的内存空间存放的是指针s的地址,即指针的地址,称为二级指针。(画图阐述)二、指针变量赋值及运算(一)指针变量赋值1、通过求地址运算符“&”给指针变量赋地址值:利用“&”运算符把一个变量的地址值赋给指针变量。例如:int a=10,*p,*q;p=&a;表示将a的地址赋给了p,我们就说p指向了变量a。(回忆scanf)(1)求地址运算符可用于变量(包括指针变量)和数组元素,但不可用于表达式、常量。因为表达式、常量无内存分配单元;(2)求地址运算符只能放在运算对象的左边;(3)&右边的运算对象的类型必须与被赋值的那个指针变量的基类型是严格相同的。(4)理解:把(int *)理解为一个类型,这样的话对于上例,若是p=a;则错了,因为a是int型的,而p为(int *),而在a右边加上&就可赋给p了,也就是说在int类型变量右边加上&则变为了(int *),同理float变量右边加上&则变为(float *)类型。那么在(int *)指针变量右边加上&则变为(int *)类型(二级指针)。而事实上,不存在(int *)和(int *)类型。2、通过其他指针变量获得地址值:类型相同的指针变量之间可以相互赋值,从而使两个指针变量指向同一地址。例如:int *p,*q,a;p=&a;q=p;p和q指向同一个变量。(强调:赋值号两边的指针变量的“基类型”必须相同。)3、通过标准函数获得地址值:通过C语言中的标准库函数的malloc和calloc函数动态分配内存中的存储单元,并把存储单元的起始地址付给指针变量,从而是指针变量指向某一连续的内存空间。(后续内容)4、给指针变量赋“空”值:含义是该指针变量不指向任何变量。格式:int *p;p=NULL;也可以是p=0或者p=0;(NULL的ASCII值为0,0也代表空值Page27)(1)此时指针p不是指向地址为0的存储单元,而是具有一个确定的值“空”;(2)不能通过一个空指针去访问一个存储单元。(二)间接访问运算符(引用内存单元)1、间接访问运算符:*2、含义:*p表示访问p所指向变量的值(p为指针变量)例:int a=8,b,*p;p=&a;b=*p;含义是把指针变量p所指向的变量a的值赋给变量b,此处*p意味着取指针变量所指向变量的内容。将指针变量所指向的变量a中存放的数据加1之后赋给变量b,以下语句是等价的:b=a+1;b=*p+1;b=*(&a)+1;b=*p+=1;b=+*p;(1)间接访问运算符必须出现在运算对象的左边,运算对象可以是地址(比如&a)或指针变量。(2)取地址运算符“&”和间接访问运算符“*”优先级相同(与+相同),单目、右结合,那么*(&a)可写为*&a。例如:b=*p+;右结合、自右向左运算、相当于b=*(p+);*是加在表达式(p+)上的,是对表达式值间接访问。3、间接访问运算符与指针变量定义中的“*”是不相同的:当定义一个指针变量时,“*”是一个说明符,说明一个变量是一个指针变量,而“*”作为间接访问运算符时意味着取指针变量所指向变量的内容。例:main()Int a=7,b=8,*p,*q,*r;p=&a;q=&b;r=p;p=q;q=r;printf(“%d,%d,%d.%d”,*p,*q,a,b);(三)指针移动移动指针就是通过赋值运算,使指针变量加上或减去一个整数,使指针变量指向相邻的存储单元。指针每移动一次则移动一个存储单元。例:p为int类型的指针,且p指向的内存地址为1200,则p=p+1;p指向了1204的存储单元。(画图说明)所以此处1代表是一个存储单元,而不是1个字节,具体这个存储单元是多大,要看指针变量的“基类型”。(四)指针比较设p、q指向同一数据集合的指针变量,如果pq为真表明p指针变量所指的元素在q指针变量所指向的元素之后。同理还有=、=、=、!=都是用来判别同一数据集合中元素的位置关系的。能够用来比较的指针,都可以使用减操作,例如:p-q,结果是存储单元的个数。(画图说明)三、函数之间地址值的传递1、传值与传址调用:函数调用过程中的参数传递分两类:(1)传值:普通变量作为实参的调用为传值调用,形参改变时实参不变,值单向传递。(2)传址:当函数的形参为指针变量时;则调用该函数时,对应的实参也必须是与形参“基类型”相同的地址值或指针变量。形参变化,实参变化。例1:int f(int *a,int *b)int s;s=*a+*b;return s;void main()int x=2,y=4,s;s=f(&x,&y);printf(%d,s);例2:传值调用:void swap(int x,int y)int t;t=x;x=y;y=t;printf(%d %d,x,y);void main()int a=3,b=4;swap(a,b);printf(%d %d,a,b);传址调用:void swap(int *a,int *b) int t; t=*a;*a=*b;*b=t;void main()int a=3,b=4; printf(1)a=%db=%dn,a,b); swap(&a,&b);printf(2)a=%db=%dn,a,b);例3:#includevoid fun(int *a,int *b) int *c; c=a;a=b;b=c;main() int x=3,y=5,*p=&x,*q=&y; fun(p,q);printf(%d,%d,*p,*q); fun(&x,&y);printf(%d,%dn,*p,*q);程序的结果是:3, 5, 3, 52、函数返回地址:函数返回值类型不仅可以是简单数据类型,还可以是代表地址的指针类型。例:int *fun(int *,int *);main()int a,b,*p;scanf(%d%d,&a,&b);p=fun(&a,&b);printf(a=%d,b=%d,*p=%dn,a,b,*p);int *fun(int *x,int *y)if(*x*y)return x;return y;第七章 数组一、数组概念:1、数组是一组具有相同类型的数据的集合,这些数据称为数组元素。例如:1,2,3整型数组,1,2,3称为数组元素;2、数组在内存中占据连续的内存空间;3、同一数组中元素类型相同,元素的名字包含相同的数组名和不同的下标;4、根据元素下标的个数可以把数组分为:一维数组、二维数组和多维数组。二、一维与二维数组(一)一维数组1、定义:类型名 数组名常量表达式;例如:int a5;定义了一个一维数组,数组名为a,包含5个int类型元素。(1)数组名是用户定义标识符;(2)方括号不可少,内表达式必须为常量表达式,不能为变量,而且常量表达式的值为正整数,表示数组元素的个数,也称为数组的长度。上例中方括号的5规定了a数组有5个元素,分别是a0、a1、a2、a3、a4。(3)每个元素的下标只有一个,范围:0常量表达式值-1。(4)定义之后,a数组在内存中占用5个连续的存储单元,每一个存储单元存放一个整型数据,占用4Bytes内存空间。(画图说明)例:要求定义具有10个int型元素的一维数组a,则下列定义语句中错误的是A)#define N 10 int aN;B)#define n 5 int a2*n;C)int a5+5;D)int n=10; int an;2、初始化:定义数组的同时,对数组元素赋初值。有以下几种形式:(1)int a5=1,2,3,4,5;(2)int a5=1,2;(3)int a=1,2,3,4,5;(4)int a5;a0=1;a1=2;a2=3;a3=4;a4=5;注意:当指定数组长度时,不允许赋初值的个数多余数组中元素的个数,例如:int a3=1,2,3,4;是不正确的;赋初值的类型必须与数组类型一致;在单纯的数组定义中,不能省略数组长度,例如:int a;是不正确的。3、数组元素的引用:数组名下标表达式,下标表达式可以是由常量和变量构成的值为正整数的表达式。例如:int a5=1,2,3,4,5;则a0值为1,a1值为2注意以下几点:(1)数组中的元素就是一个变量,所有适合该类型变量的操作同样适用于数组。例如:a0=5;a0+;a1=a0+14;printf(“%d”,a4);(2)数组元素的下标,必须是从0开始,到数组的最大长度减1;例:int a5;a5是错的。(3)数组名代表数组的首地址,是一个地址常量,不能整体引用数组里面的所有元素。例1:main()int i,n=0,0,0,0;for(i=1;i=4;i+)ni=ni-1*2+1;printf(%d,ni);例2:main()int i;float sum,aver,b10=4,2,8,3,1,10,5,6,12,7;sum=0;for(i=0;i10;i+)sum+=bi;aver=sum/10;printf(sum=%f aver=%f,sum,aver);例3:main()int i,cnt,b10=58,99,60,42,75,64,86,92,100,71;cnt=0;for(i=0;i=60)cnt+;printf(cnt=%d,cnt);(二)二维数组1、定义:数组元素具有两个数组下标的数组,定义格式如下:类型名 数组名常量表达式1常量表达式2;例如:int a23;定义了一个2*3(2行3列)的二维数组,数组名为a,包含6个int类型的元素,可以理解为是一个矩阵,每个元素有行下表和列下标,分别是该元素所在行和列的编号。(画图说明)(1)数组名是用户定义标识符;(2)数组名后面的两对方括号不可少,之间不可有空格,括号中必须是值为正整数的常量表达式,不可为变量;(3)定义int a23;后,a数组在内存中占用6个连续的存储单元,按照行顺序依次存储。(画图说明)(4)把二维数组看成是多个一维数组的组合,比如:int a23;就可看成是一维数组a0和a1的组合,并且a0、a1现在就是一个地址。2、初始化:在定义二维数组时,系统只是为它分配内存空间,但是没有对其赋初值,因此要初始化,有这么几种形式:(1)int a23=1,2,3,4,5,6;(2)int a23=1,2,3;(3)int a23=1,2;(4)int a23=1,2,3,4,5,6;(5)int a3=1,2,3,4,5,6;注意:所赋初值的类型与数组元素的类型一致;每一行所赋初值的个数不能独有该行的元素数,即列数;行数也不能多于数组应有的行数。比如:int a23=1,2,3,4,2,3,5,1,2;是不正确的。在初始化过程中,不允许缺省常量表达式2(列数),比如:int a2=1,2,3;是错误的;在单纯定义数组不赋初值时,常量表达式1(行数)和常量表达式2(列数)都不能省略,比如:int a3;是错误的。3、二维数组元素的引用:格式:数组名 行下标列下标;例如:int a23=1,2,3,4,5,6;它的元素a00、a01、a02、a10、a11、a12。注意:(1)数组中的行下标和列下标都是从0开始,到下标的上界减1;(2)二维数组是一些类型相同的元素的集合,但是不能用数组名来代表所有的元素;(3)列下标变化比行下标变化快。Page101 习题三、数组应用常用循环来控制数组元素,一维数组用一层循环,二维数组用二层循环,一般外层控制行变化,内层控制列变化,因为列变化快。例1:main()int i,max,min,a10;for(i=0;i10;i+)scanf(%d,&ai);max=a0;min=a0;for(i=1;i10;i+)if(maxai)min=ai;printf(max=%d min=%d,max,min);例2:main()int i,j,a,b5=4,2,8,3,1;for(i=0;i5;i+)for(j=i;j5;j+)a=bi;bi=bj;bj=a;for(i=0;i5;i+)printf(%d,bi);例3:#include stdlib.hmain()int i,a,b10;for(i=0;i10;i+)bi=rand(20);printf(%d,bi);for(i=0;i5;i+)a=bi;bi=b10-1-i;b10-1-i=a;for(i=0;i10;i+)printf(%d,bi);例4:main()int i,b10=58,99,60,42,75,64,86,92,100,71;for(i=4;i9;i+)bi=bi+1;for(i=0;i9;i+)printf(%d,bi);例5:main()int i,j,b10=58,99,60,42,75,64,86,92,100,71;j=-1;for(i=0;i10;i+)if(bi=60)j=i;printf(j=%d,i);Page103 习题第十二章 数组与指针一、一维数组与指针1、一维数组的数组名代表一维数组在内存中的首地址,例如: int *p, a5=1,2,3,4,5; p=a;(1)数组名a表示数组的首地址。因此p=a是让指针p指向数组a的起始地址;(2)a是一个地址常量,它永远指向数组a的首地址,不能对a进行重新赋值,例如:a=&i或a+是错误的。2、一维数组元素的引用法对数组元素ai的4种等价的引用方法:通过指针引用数组元素、通过数组首地址引用数组元素、用带下标的指针变量引用一维数组,具体如下所示:(1)ai(2)pi(3)*(a+i)(4)*(p+i)例1:main()int a5,*p,i;for(p=a,i=0;i5;i+)scanf(%d,p+i);for(p=a;pa+5;p+)printf(%d,*p);例2:main()int a5,i;for(i=0;i5;i+)scanf(%d,a+i);for(i=0;i5;i+)printf(%d,*(a+i);例3:main()int a10=1,2,3,4,5,6,7,8,9,10,*p=&a3,*q=p+2;printf(%dn,*p+*q);例4:main()int i,s=0,t=1,2,3,4,5,6,7,8,9;for(i=0;i9;i+=2)s+=*(t+i);printf(%dn,s);3、一维数组元素地址的引用方法对ai的地址的4种等价的引用方法:(1)&ai(2)&pi(3)a+i(4)p+i4、若指针变量p指向了一维数组a的首地址。如:int a10; int *p=a;则有下面的等价关系:(1)a+i等价于p+i,都与&ai相同。(2)*(a+i) 等价于*(p+i) 都与ai相同。(3)ai等价于pi(4)p+、+、p+=1、p=p+1作用都是让p指向下一个存储单元;p-、-、p-=1、p=p-1作用都是让p指向上一个存储单元。(5)*p+与*(p+)等价,都是得到p当前所指向的元素的值,并让p指向下一个存储单元;*p-与*(p-)等价,都是得到p当前所指向的元素的值,并让p指向前一个存储单元。(6)*+p与*(+p)等价,都是先让p指向下一个存储单元,再取出数组元素;*-p与*(-p)等价,都是先让p指向前一个存储单元,再取出数组元素。(7)(*p)+、+(*p)、+*p的作用都是让p当前所指的数组元素的值增加;(*p)-、-(*p)、-*p的作用都是让p当前所指的数组元素的值减。二、二维数组与指针(一)二维数组的首地址和数组元素的地址1、二维数组是由多个一维数组构成例:int a23=1,2,3,4,5,6,*p,i;(画图说明)(1)a0、a1可认为是一维数组名,是地址常量,值为数组第一个元素的地址;(2)p=a0;或p=a1;是合法的,取p=a0;此时p指向了a0所指向的存储单元,即a00,a0i、pi、*(a0+i)、*(p+i)等价;(3)二维数组中个元素在内存中是连续存放的,同一行按列标连续存放,紧跟着存下一行,所以a10紧接在a02后边,因此p3虽越边界,但仍有效,指向a10;p3等价于a03,所以a03实际上是a10。2、二维数组名也是一个地址常量(1)其指向二维数组的第一个元素;(2)int a23,*p;指针a的“基类型”是一个3个元素的数组,所以a+1表示的是a1的地址,所以a+i与&ai等价,*(a+i)与ai等价,而且不能p=a;。3、二维数组元素地址的引用方法有二维数组amn,对数组元素aij的地址的5种等价引用方法:(1)&aij(2)ai+j(3)*(a+i)+j(4)a00+i*n+j(5)a0+i*n+j4、二维数组元素的引用方法有二维数组am

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论