关于数组
#C
2024-08-31
数组就是一片连续的内存空间,并且被划分成大小相等的小空间。
为什么数组下标从0开始?
寻址公式:i_address = base_addr + i * sizeof(element)
- 如果下标从 0 开始,第一个元素
arr[0]
的地址为A + 0 * S = A
,这与数组的基地址相同,无需额外的计算。 - 如果下标从 1 开始,第一个元素
arr[1]
的地址会是A + (1-1) * S = A
,虽然结果相同,但在逻辑上需要多一层计算处理,即计算 (1-1) 的结果。
从来只有一维数组
1 |
|
数组名称是 data ,数据类型是 int[2][2]。 data[0] 或 data[1] 的数据类型是 int[2]。 data[0][0] 或 data[0][1] 的数据类型是 int。
因此,这就能很好理解数组计算长度的公式了。
1 |
|
我们说数据类型指示数据的范围,data 的数据类型代表的范围是 4 个 int 类型,而 data[0][0] 的数据类型代表的范围是 1 个 int 类型。
小心数组退化为指针
因为数组作为实参传递给函数的时候,回退化为指针,而我们遍历数组需要长度,这个时候你再用前面的方式计算数组长度就会出现错误,所以我们希望你在传递数组作为实参的时候,记得提前计算长度并也作为实参传递进去。
于此同时,我们应该在传递数组作为实参的时候,类型应该写成 指针,这样读者就会认为这是传递进来的一个数组,且已退化为指针。如果你不是这样做,而是像这样 int[] data 或 int[2] data ,那么读者虽然能看出这是一个数组,但是容易忘记它已经退化为指针。
1 |
|
如果你非要这么做,即以数组的视角去定义形参,那么访问数组元素需要用如下方式。
1 |
|
你可能想问,如果是多维数组,我们该如何传递长度呢?只需要传递可以被省略的那个数即可,比方说 data[2][2] 可以省略为 data[][2],也就是说第一个可以被省略。或者,你直接把行和列的长度都传进去,因为我们通常不会超过二维数组,所以这不是什么难考虑的事情。