4、一维数组在内存中的存储
接下来我们探讨数组在内存中的存储。看下图︰
//打印地址 #include <stdio.h> int main() { int arr[10] = { 0 }; int i = 0; for (i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i) { printf("&arr[%d] = %p\n", i, &arr[i]); } return 0; }
通过观察我们可以看到:
1.一维数组在内存中是连续存放的
2.随着数组下标的增长,地址是由低到高变化的
数组地址连续存放有什么实际意义或作用吗?
看下面这个例子:
这个例子可以很好说明刚刚的问题,正因为数组是连续存放的,通过数组首元素的地址往后找可以找到每一个数组对应的元素!
二、二维数组
1、二维数组的创建
二维数组的使用也是通过下标的方式。几行几列,看代码:
//二维数组创建 int arr1[3][4]; char arr2[3][4]; double arr3[4][5];
当我们创建一个二维数组int arr[3] [4] 后,在我们的脑海中要形式对应的三行四列二维数组,这个数组的每个元素都是int类型。(二维数组有行列之分)
2、二维数组的初始化
//初始化---创建的同时给赋值 方式① int arr1[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };//完全初始化
三行四列的数组arr1有12个元素,我们可以在初始化的时候直接用大括号将12个元素括起来赋值给arr1。
int arr[3][4]={1,2,3.{4,5,67,8,9}}
思考:如果说我们给的元素个数大于12个或小于12个会发生什么呢?
(1)大于12个元素时:程序运行时,编译报错,无法正常执行,报错原因就是初始值设定项太多。从这个报错我们大概就能知道对于数组创建,编译器会检查初始项是否大于数组的长度。这个其实也很好理解,数组本质也是变量,变量的创建需要向内存申请空间,如果初始值设定项占用的空间大于数组申请的空间,就会“越界访问”(比如数组申请一块40个字节大小的空间,我们在设置初始项的时候给了11个int类型的值,也就是44个字节,超过数组本身可以访问空间的大小了)。
(2)小于12个元素时:数组会进行不完全初始化,前几项会赋值成初始化的值,后面几项会自动赋初始值0填充。(如果是字符数组,会用\0填充,\0的ASCII码值是0)
**注意:**二维数组在创建的时候**行可以省略,列不能省略**(第一个[ ]中的值可以不写,第二个[ ]值必须写)
3、二维数组的使用
二维数组的使用方式也是通过下标的方式。二维数组的行和列下标都是从0开始的:
#include<stdio.h> int main() { int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 }; int i = 0; int j = 0; for (i = 0; i < 3; i++) { for (j = 0; j < 4; j++) { printf("%3d", arr[i][j]); } printf("\n"); } return 0; }
4、二维数组在内存中的存储
之前我们提到在创建二维数组的时候,会在脑海中将其想象成一个二维表(有行和列),但是二维数组在内存的存储形式是什么样的呢?跟我们刚刚想的二维表形式一样存储方式吗?
为了研究二维数组的存储,这里我们可以尝试将二维数组的每个元素都打印出来:
我们可以看到二维数组的每个元素之间均相差4个字节,所以二维数组在内存中也是连续存放的!这个连续存放有两层含义:1.每一行内部的元素连续存放 2.行与行之间连续存放