数组Word文档下载推荐.docx
《数组Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《数组Word文档下载推荐.docx(49页珍藏版)》请在冰豆网上搜索。
![数组Word文档下载推荐.docx](https://file1.bdocx.com/fileroot1/2022-11/16/82760b5d-3e32-4966-8a22-57f1d4741476/82760b5d-3e32-4966-8a22-57f1d47414761.gif)
17.5.4二维及更多维数组作为函数参数
17.5.5函数的返回值类型不能是数组
17.6sizeof用在数组上
17.6.1用sizeof自动计算元素个数
17.6.2sizeof对数组参数不可用
变量需要占用内存空间,内存空间有地址。
不同数据类型的变量,可能占用不同的内存大小及有不同的内存结构。
以前我们所学都称为“简单数据类型”,如:
int,char,float,double,bool。
像char,bool,只占用一个字节,所以我们不去管它的的“结构”,其余如int,float,double占用多个字节,但比较简单,适当的时候我们会去探讨4个字节是如何组成一个整数。
后来我们学习了数组。
数组变量占用内存的大小是不定的,因为不同的数组变量除了类型可以不同,还可以拥有不同个数的元素,这两点都影响它的大小。
因此,数组是我们第一个要着力研究它的结构的数据类型。
和后面我们还要学习的更多数据类型相比,数组的结构还是相当简单的。
简单就简单在它的各个元素大小一致,整整齐齐地排列。
17.1.1数组的内存结构
声明一个整型变量
inta;
系统会为该变量申请相应大小的空间,一个int类型的变量时,需要占用4个字节的空间,如下图:
也就是说,一个int类型的变量,它的内存结构就是“4个连续的字节”。
当我们声明一个数组:
intarr[100];
我们可以想像,arr数组在内存中占用了100*sizeof(int)个字节。
现在请大家打开Windows的画笔程序,家画一个数组的内存结构示意图。
17.1.2数组的内存地址
一个int类型变量,占用4个字节的内存,其中第一个字节的位置,我们称为该变量的内存地址。
同样,一个数组变量,占用一段连续的内存,其中第一个字节的位置,我们称为该数组变量的内存地址。
还记得&
这个符号吗?
通过它我们可以得到指定变量的内存地址。
cout<
<
&
a<
endl;
&
称为“取址符”。
如果你有点记不清,可以查看以前的课程。
本章第一个需要你特别注意的内容来了:
查看数组变量的地址,不需要使用&
。
下面的话是一个原因也是一个结论,你必须记住。
C,C++语言中,对数组变量的操作,就相当于直接对该数组变量的地址的操作。
因此,想要查看一个数组变量的地址,代码为:
intarr[10];
arr<
//注意,arr之前无需&
现在,请大家打开CB,然后将上面代码写成完整的一个控制台程序,看看输出结果。
17.1.3数组元素的内存地址
一个数组变量包含多个连续的元素,每一个元素都是一个普通变量。
因此,对就像对待普通变量一样可以通过&
来取得地址:
//查看数组中第一个元素的地址:
arr[0]<
例一:
现在,请大家在CB里继续上一小节的代码,要求:
用一个for循环,输出数组arr中每一个元素的地址。
如果你已完成,现在来看我的答案。
#include<
iostream.h>
...
for(inti=0;
i<
10;
i++)
cout<
arr[i]<
cin.get();
我们把它和前面输出数组地址的例子结合起来,然后观察输出结果。
//输出数组的地址:
"
数组arr的地址:
<
//输出每个元素的地址:
元素arr["
i<
"
]的地址:
输出结果:
第一个要注意的的是头两行告诉我们,整个数组变量arr的地址,和第一个元素arr[0],二者的地址完全一样。
事实上,数组和元素,是对同一段内存的两种不同的表达。
把这一段内存当成一个整体变量,就是数组,把这段内存分成大小相同的许多小段,就是一个个数组元素。
请参看下图:
(分开一段段看是一个个元素,整体看称为一个数组,但二者对应的是同一段内存)
第二个要注意的,大家算算相邻的两个元素之间地址差多少?
比如&
arr[1]-&
arr[0]=1245028-1245024=4个字节。
这4字节,就是每个数组元素的大小。
当然,这里是int类型,所以是4字节,如果是一个char或bool类型的数组,则每个元素的大小是1。
根据这两点,我来提几个问题:
1、如果知道某个int类型数组的地址是1245024,请问下标为5的元素的地址是多少?
2、如果知道某个char类型的数组,其下标为4的元素地址为:
1012349,请问下标为2的元素地址是多少?
由于可通过sizeof()操作来取得各类型数据的大小,所以我们可以假设有一数组:
Tarr[N];
//类型为T,元素个数为N。
存在:
arr[n]=arr+sizeof(T)*n;
(0<
=n<
N)
或者:
arr[n]=arr+sizeof(arr[0])*n;
17.1.4数组访问越界
上一章我们说过“越界”。
由于这一问题的重要性,我们需要专门再说一回。
越界?
越谁的界?
当然是内存。
一个变量存放在内存里,你想读的是这个变量,结果却读过头了,很可能读到了另一个变量的头上。
这就造成了越界。
有点像你回家时,走过了头,一头撞入邻居家……后果自付。
数组这家伙,大小不定!
所以,最容易让程序员走过头。
我们通过数组的下标来得到数组内指定索引的元素。
这称作对数组的访问。
如果一个数组定义为有n个元素,那么,对这n个元素(0到n-1)的访问都合法,如果对这n个元素之外的访问,就是非法的,称为“越界”。
比如,定义一个数组:
那么,我们可以访问arr[0]~arr[9]这10个元素。
如果你把下标指定为10,比如:
inta=arr[10];
//访问了第11个元素。
这就造成了数组访问越界。
访问越界会出现什么结果了?
首先,它并不会造成编译错误!
就是说,C,C++的编译器并不判断和指出你的代码“访问越界”了。
这将很可怕,也就是说一个明明是错误的东西,就这样“顺利”地通过了编译,就这样不知不觉地,一个BUG,“埋伏”在你的程序里。
更可怕的是,数组访问越界在运行时,它的表现是不定的,有时似乎什么事也没有,程序一直运行(当然,某些错误结果已造成);
有时,则是程序一下子崩溃。
不要埋怨编译器不能事先发现这个错误,事实上从理论上编译过程就不可能发现这类错误。
也不要认为:
“我很聪明,我不会犯这种错误的,明明前面定义了10个元素,我不可能在后面写出访问第11个元素的代码!
”。
请看下面的代码:
for(inti=1;
=10;
{
arr[i];
}
它就越界了,你看出原因了吗?
再说上一章的成绩查询。
我们让用户输入学生编号,然后查该学生的成绩。
如果代码是这样:
intcj[100];
//让用户输入学生编号,设现实中学生编号由1开始:
请输入学生编号(在1~100之间):
inti;
cin>
>
i;
//输出对应学生的成绩:
cj[i-1];
这段代码看上去没有什么逻辑错误啊。
可是,某些用户会造成它出错。
听话的用户会乖乖地输入1到100之间数字。
而调皮的用户呢?
可能会输入101,甚至是-1——我向来就是这种用户——这样程序就会去尝试输出:
cj[100]或cj[-2]。
解决方法是什么?
这里有一个简单,只要多写几个字:
请输入学生编号(在1~100之间如果不输入这个范围之内数,计算机将爆炸!
):
系主任在使用你的这个程序时,十个指头一定在不停地颤抖……
理智的作法还是让我们程序员来负起这个责任吧,我们需要在输出时,做一个判断,发现用户输入了不在编号范围之内的数,则不输出。
正确答案请看上章。
为什么数组访问越界会造成莫名其妙的错误?
前面一节我们讲到数组占用了一段连续的内存空间。
然后,我们可以通过指定数组下标来访问这块内存里的不同位置。
因此,当你的下标过大时,访问到的内存,就不再是这个数组“份内”的内存。
你访问的,将是其它变量的内存了。
前面不是说数组就像一排的宿舍吗?
假设有5间,你住在第2间;
如果你晚上喝多了,回来时进错了房间,只要你进的还是这5间,那倒不会有大事,可是若是你“越界”了。
竟然一头撞入第6间……这第6间会是什么?
很可能它是走廊的尽头,结果你一头掉下楼,这在生活中是不幸,可对于程序倒是好事了,因为错误很直接(类似直接死机),你很容易发现。
可是,如果第6间是?
?
据我所知,第6间可能是小便处,也可能是女生宿舍。
事实要开始变得复杂。
生活中,有很多事物,仅仅用一维数组,将无法恰当地被表示。
还是说学生成绩管理吧。
一个班级30个学员,你把他们编成1到30号,这很好。
但现在有两个班级要管理怎么办?
人家每个班级都自有自的编号,比如一班学生编是1~30;
二班的学生也是1~30。
你说,不行,要进行计算机管理,你们两班学员的编号要混在一起,从1号编到60号。
另外一种情况,仍然只有一个班级30人。
但这回他们站到了操场,他们要做广播体操,排成5行6列。
这时所有老师都不管学员的编号了,老师会这样喊:
“第2排第4个同学,就说你啦!
踢错脚了!
假设我们的校长大人要坐在校长室里,通过一个装有监视器的电脑查看全校学员做广播体操,这时,我们也需要一个多维数组。
17.2.1二维数组基本语法
语法:
定义一个二维数组。
数据类型数组名[第二维大小][第一维大小];
举例:
intarr[5][6];
//注意,以分号结束。
这就是操场上那个“5行6列的学生阵”。
当然,哪个是行哪个列凭你的习惯。
如果数人头时,喜欢一列一列地数,那你也可以当成它是“5列6行”——台湾人好像有这怪僻——我们还是把它看成5行6列吧。
现在: