数组在C中是常用的数据结构,储存方式上表现为一段连续的内存。因此也可以用下标去访问数组中的元素,因为根据变量类型,计算机可以快速算出每个元素的地址。数组通常用于存储同一类型的数据。
声明数组
数组和指针的关系也很密切,当声明一个数组,数组的名字就是它的首地址。
‘ * ’和‘ [] ’都是解引用符,也就是说*(x+1)和x[1]是一样的。
数组的类型
数组的类型会影响具体占用多少内存,和声明数据类型一样,比如int x占4,那int x[3]占3*4=12。 可以看到,x到x+1之间差了4Bytes。(C-8=4)16进制
字符数组
字符数组可以用来表示字符串,C里常用,用法和数组是一样的,不过结尾会有一个‘\0’表示结束。
真的只会遇到‘\0’才停下。(\0就是NULL)
数组遍历
因为是连续的一段内存,所以遍历其实很简单,需要注意的是写循环的时候,不要超出范围。声明的是x[3],遍历就写(i=0;i<3;i++)就行了,因为数组的序号从0开始,而不是从1,所以我们需要遍历的是0到2,而不是1到3。
超出范围之后就是垃圾数据了,我看挺多初学者遍历的时候没搞明白数组范围,打印出乱码,以为是别的地方有错误的。
元素添加和删除
数组一般生成了就很难去改变它的size大小,你声明它是多大就多大。往空的地方添加很简单,但是如果是想在中间插入就比较麻烦,一般是要把插入位置之后的元素往后移一格,再将元素插入;删除也一样,如果是在中间删除,还要保证数组连续的话,要把删除位置后的元素往前移。
还有一个问题就是,如果插入的时候,数组满了怎么办,一般就是建一个新的更大的数组,把原数组拷贝过去;C++里也可以用容器vector+迭代器完成这一操作。不过因为数组size很难改变的特点,如果需要频繁地增加删减,对数据的连续性也不是必须要求的话,还是建议使用链表。
传递数组
怎么把数组传到函数里。之前说过数组就是这串连续内存的首地址,所以传过去的就是地址咯。
直接把指针传过去,很明显大小是不匹配的,系统没有帮你存数组大小,实际上它理解的是你传了一个指针,如果在函数里要遍历数组的话,很容易超范围或者只遍历了一半,这个时候,要把原数组的大小一起传过去。
二维和多维数组
数组可以理解成指针,二维数组就是指向指针的指针,二级指针,多维同理。
声明的时候,只有最外层可以空着不写,里面的必须填好大小。
和一维数组一样,名字还是指向首地址。而如果只解一层引用,打印出来的还是地址。
{1,2,3}占12个字节,事实上x[1]到x[0](16进制)是100(64)-88(58)是12。
函数传参和声明一样的,最外层的可以不写,里面的大小要补全。