C语言-数组

一、一维数组

1、一维数组创建

数组元素的数据类型+数组名+[常量表达式]
对于中括号的内容:
常量表达式用来表示数组的大小,指定数组当中有多少个元素。
表示数组的大小任何时候都可以用常量或者常量表达式。
在C99标准之前,只能用常量或者常量1表达式
在C99标准之后,可以用1变量表示数组的大小,用来表示变长数组,变长数组的意思是可以用变量来表示数组的长度。

2、一维数组初始化

当指定元素个数时:
分为不完全初始化和完全初始化
当不完全初始化时,由于指定了元素的个数,剩余的元素默认为0。
当完全初始化时,按顺序存入就行了。
当不指定元素个数时:
数组会根据初始化的内容,确定元素的个数。
例子:

char arr1[]={'a','b','c'};
char arr2[]="abc";

数组会根据初始化的内容,确定元素的个数,数组arr1的元素的个数是3,
数组的元素的个数是4。
arr2存放的是字符串,字符串末尾有\0,\0在内存中也会占用空间,所以arr2中的元素个数是4。

3、一维数组的使用

使用之前应了解数组是如何在内存中存储的:
数组在内存中是连续存放的,在内存中申请空间,在栈中存取,数组中的元素按顺序排列。
想象成在一层楼中,许多个房间按顺序排列,并且每个房间都有编号。
数组中的元素同样也有编号,每个元素都对应着下标,从0开始。

使用下标引用操作符,获取下标,来定位元素。

4、一维数组在内存中的存储

一维数组在内存中是连续存放。
在了解之前,先举个小例子
现在有一层楼,这一层有好多个房间,房间上都有门牌号,此时让两个人来,各自挑四间连续的房间,意思就是挑的四件房间必须是门牌号必须是连续的,但是我们不知道他俩挑的哪的,询问之后,他俩各自挑的的第一间房的编号相差4,这意味着什么?意味着这两个人的四间房是挨着的。
下面看真实的:
数组是存放元素的,且每个元素都有下标,和房间的编号一样。
一个整型数组存放的元素,一个元素在内存中占四个字节,一个字节对应一个地址编号,一个整型元素占四个地址编号,
此时在控制台打印每个元素的地址编号发现,两个相邻元素所占的第一个字节所对应的地址都相差4,就说明了数组中的元素在内存中是连着放的,也就说明了数组在内存中是连续存放的。
随着下标的增长,地址编号也在由低到高有规律的增长。

二、二维数组

1、二维数组的创建

创建二维数组的原因:
我们现在想存几组相同类型的元素,一维数组只能存取一组相同类型的元素,所以就会产生二维数组。
例如:
1234
4567
0987
我们想要存上面几组的元素,都是整型,并且我们想要存三行,一行有四个数据,所以有三行四列。
此时二维数组可以这样创建:int arr[3][4]

2、二维数组的初始化

初始化的意思是当创建好数组之后,向数组里面放一些合适的值。
可以把数组比做一个篮子,初始化就是向里面放东西。

初始化的方式有两种:
第一种是完全初始化,数组指定了放多少数据,就向里面放多少数据。
例如:int arr1[2][2] = { 1,2,3,4},数组指定了放两行数据,一行放两个数据,需要放四个数据,就初始化四个,按照顺序向里面放。

第二种是不完全初始化,数组指定了放多少数据,向里面放完之后,不满足数组指定的,则默认数据为0进行存放。
向数组里面存放的时候,有两种存放的方式:
按顺序存放: 根据数组指定的数据,按照初始化的顺序进行存放。
例如:int arr2[2][2] = {1,2},指定了要放四个数据,但是却只初始化两个,则按照顺序放,一行放两个,1和2放第一行,第二行初始化为0。
对数据分组存放: 根据数组指定的数据,按照分的组进行存放。一组中如果数据不够,则默认数据为0进行存放。
例如:int arr3[2][2] = {{1},{2}}
数组arr2将1和2放入了第一行,如果我们想把2放入第二行,可以进行分组,一组的数据放在一行。
将1放入第一行,根据指定的元素个数,一行应该放两个数据,则另外一个默认为0存放。
第二行也是同理。

一种特殊情况是,数组创建的时候,没有指定行,只指定了一行有多少列:
在了解之前,先讲一个上学的例子:
上中学时,老师会让我们跑步,跑步之前,让我们排好队,老师说大家站三排,同学们不能排好队,因为老师没有说一排站几个同学,也就是没说一排有几列,没有规定好,如果不规定好,一排可以随意站,第一排可以站1个同学,第二排可以站2个同学,第三排可以站剩余的同学,有很多种情况,不能确定,所以老师必须规定好,一共有几排,一排有几列。

下面正式讲我们C语言的例子:
和刚才的排队一个道理,如果二维数组在创建的时候,只指定行,不指定列,那么向数组里面存数据的时候,不知道怎么存,没有告诉数组一行可以放多少个数据。

根据数组指定的数据个数进行初始化,如果初始化的数据不够,默认数据为0进行存放。

3、二维数组是如何使用的

二维数组也是通过访问下标,来定位元素的。
一维数组是确定房间的编号,也就是使用每一个元素所对应的下标,来定位元素的。
此时一维数组是一层楼房,那么二维数组是多层楼房,首先应先确定层数,在确定房间编号,使用每一个元素所对应的下标,来定位元素。
所以说,二维数组是对行和列进行编号,从0开始,通过确定行和列的下标,定位元素。

4、二维数组在内存中的存储方式

二维数组在内存中也是连续存放的
具体细节:
通过在控制台打印整型数组中的每个元素发现,布局方式和一维数组的布局方式相同。
相邻两个元素的地址编号都相差4,并且一个元素占四个字节,一个字节对应一个地址编号,一个元素对应四个地址编号,元素在内存中是连在一块存放的。
所以也可以看出,二维数组在内存中也是连续存放的。
总结:
二维数组和一维数组在内存中的布局方式是一样的,但是访问的形式不一样。

5、对于二维数组的理解

第一个理解:
可以把二维数组看作一维数组:
将二维数组的每一行作为元素,那么此时二维数组就是一维数组。
第二个理解:
可以把二维数组看做一维数组的数组:
先把二维数组看作一维数组,
把每一行看作一维数组的元素,
再把这每一个元素看作一个一维数组,
所以二维数组可以理解为一维数组的数组。
每一行看作一个元素,一个元素可以看作一个一维数组,假如有三行,就有三个元素,就有三个一维数组。
将这每一行看作一维数组之后呢:
arr[0]是第一行这个一维数组的数组名,
arr[1]是第二行这个一维数组的数组名,
arr[1]是第三行这个一维数组的数组名,
在通过使用列的编号,可以定位每一行每一列的元素。

比方说要访问第一行的每一个数据,使用arr[0][j],访问 联想一维数组访问元素时,使用arr[j],访问
所以就可以把arr[0],看做每一行的数组名。

三、数组越界

什么是数组越界:
当访问元素时,由于下标和房子的编号是一个道理,都是有范围的,如果使用不在下标范围内的下标去访问元素,就是数组越界,就会出现数组越界。
但出现数组越界,编译器并不会报错,需要自己细心检查。
对于在一维数组里面去访问元素时:
当访问每一个元素时,如果此时的下标的范围是0-9,使用下标为10时,就会出现越界访问。
对于在二维数组去访问元素时:
当分别访问每一行的每一列的元素时,如果每次在访问某一行的元素的时候,都会额外访问到下一行的元素,这只是在自己范围内越界,并不会出错,但如果一直这样下去,到最后一行的时候,照样会额外访问,但此时已经是最后一行了,所以就会出现越界访问。
所以二维数组也有可能出现越界访问。

四、数组作为函数参数

1、数组名是什么?

数组名是首元素的地址 (arr)
但是有两个例外,数组名代表整个数组
第一个例外:使用数组名求数组的长度,求出来的是整个数组的长度:sizeof(arr)
第二个例外:使用数组名求数组的地址,求出来的是代表第一个元素的地址,但表示的是,整个数组的地址,&arr。
arr的数组长度是10*4=40个字节,占有40个地址编号,一个字节占一个地址编号,一个整型占四个字节,一个整型占四个地址编号。
深刻理解&arr和&arr[0]的区别:
通过使他们的地址分别+1,来看他们最后跳到哪去了,就可以表示出他们分别代表什么?
&arr[0]+1之后,跳到下一个元素的第一个字节的地址,表示出&arr[0],代表一个元素的地址。尽管在控制台输出的是第一个字节的地址,这是以少概全。为了方便,仅使用第一个字节代表整个元素的地址。

&arr + 1之后,越过了整个数组的地址编号,跳到与数组紧挨着的一个字节的地址编号,表示出&arr,代表一个数组的地址,尽管在控制台输出的是第一个字节的地址,这里也是以少概全,为了方便,仅使用第一个字节代表整个数组的地址。

举例来说:
在这里插入图片描述

2、冒泡排序

冒泡排序的核心思想:
相邻两个元素进行比较,如果不满足我们的顺序,就进行响应的调整。
给出一组没有顺序的整数,规定进行升序处理,使用一趟冒泡排序,可以将这组数中的一个数放到它应该在的位置,也就是将这组数中最大的数挑出来,放到最右边。

可以通过小时候的排大小个的问题来进行理解。
一个班的同学站一排,从左到右两两比较,一方中较高的同学在这两方的右面,不满足这个条件的,两方进行交换一下位置,最终进行完一趟两两比较之后,最高个已经出现在队伍的最后。一直重复这个动作,并且已经排好的同学不需要在进行比较,直到全部排好为止。

这也就是冒泡排序这个名字的由来:
两两互相比较,不满足条件的,交换顺序,交换的过程就像是水中的气泡一样,在向上冒。

五、数组的应用

1、三子棋

放到另一篇博客了
博客链接:三子棋

六、对于数组知识的一些补充

1:
我们向字符型的数组存放字符串之后,
求数组的长度意思是:是求数组中元素的个数,而不是求数组中字符串中的字符的个数,这一点要分清。
具体解释:
向数组中存放字符串之后,\0和字符串同时存到了数组里面。
但计算字符串的长度时,是不会计算\0的,计算数组长度时,会计算\0。
当然要注意的一点是,计算字符串的长度可以使用strlen这个库函数,但计算数组长度,不能使用strlen函数,strlen是痴情函数,只对字符串感兴趣。

例:

char acX[] = “abcdefg”;
char acY[] = {‘a’,’b’,’c’,’d’,’e’,’f’,’g’};
A.数组acX和数组acY等价
B.数组acX和数组acY的长度相同
C.数组acX的长度大于数组acY的长度
D.数组acX的长度小于数组acY的长度
下列选项正确的是:C

很明显,数组acX比数组acY多一个元素,元素是\0。
并且这个题呢,它只能理解为求数组中元素的个数,不能理解为求字符串的长度,因为数组acY求得的长度是不固定的,没有向数组中主动放\0,计算机需要自己去内存中寻找,直到遇到\0,才会停止

2:

#include <stdio.h>
int main()
{
    int arr[] = {1,2,(3,4),5};
    printf("%d\n", sizeof(arr));
    return 0;
}

sizeof(arr)=16;
此题要计算数组在内存中所占空间的大小,一共有四个整型元素,一个整型元素在内存中占四个字节,所以一共占16个字节。
逗号表达式的值为括号中最后一个表达式的值,(3,4)是逗号表达式,值是4。所以4作为一个元素的值,3被舍弃。

3:
变量有数据类型,数组也有数据类型
一个存放五个元素的整型数组的数据类型是:int [5]

4:对于数组的理解,可以理解为一维数组是一层楼房,里面有好多个房间,一个一个的房间就是元素,房间里面放的是值。
如图所示:
在这里插入图片描述
a-j就是那些值,这些一个一个的小方框就是房间。

对数组中的值进行一些修改操作时,有两个步骤:
第一步:通过下标或者地址找到元素,也就是找到那一块空间
第二步:找到那一块空间,对里面的值进行操作。
如果在执行第二步时,将值拷贝到了一个变量中,这个变量向内存申请空间,将值的分身保存到了另一块空间中,对另一块空间的值进行修改,不会影响那一块的空间的值。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值