|
发表于 2019-2-12 18:59:41
|
显示全部楼层
首先,为了便于下面的理解,我们首先来接受一个概念:
二维数组的初始化可以按行分段赋值,也可按行连续赋值。之所以可以这样操作,是因为:二维数组在概念上是二维的,但在内存中是连续存放的;换句话说,二维数组的各个元素是相互挨着的,彼此之间没有缝隙。那么,如何在线性内存中存放二维数组呢?在C语言中,二维数组是按行排列的。比如对于int a[5][3];也就是先存放 a[0] 行,再存放 a[1] 行,再存放 a[2] 行,再存放 a[3] 行,最后粗放a[4]行;每行中的 3 个元素也是依次存放。数组 a 为 int 类型,每个元素占用 4 个字节,整个数组共占用 4×(5×3)=60 个字节。
具体我们来看一个例子,对于数组 a[5][3],按行分段赋值应该写作:
int a[5][3]={ {1,2,3}, {4,5,6}, {7,8,9}, {10,11,12}, {13,14,15} };
而按行连续赋值可以写作:
int a[5][3]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
这两种赋初值的结果是完全相同的。
那么好,上面我们重点说到了两个概念,一个是二维数组元素是连续存放的;另一个是二维数组是按行排列的。那么我们接下来再看三个概念:
1) 可以只对部分元素赋值,未赋值的元素自动取“零”值。例如:
int a[3][3] = {{1}, {2}, {3}};
是对每一行的第一列元素赋值,未赋值的元素的值为 0。赋值后各元素的值为:
1 0 0
2 0 0
3 0 0
再如:
int a[3][3] = {{0,1}, {0,0,2}, {3}};
赋值后各元素的值为:
0 1 0
0 0 2
3 0 0
2) 如果对全部元素赋值,那么第一维的长度可以不给出。例如:
int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
可以写为:
int a[][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3) 二维数组可以看作是由一维数组嵌套而成的;如果一个数组的每个元素又是一个数组,那么它就是二维数组。当然,前提是各个元素的类型必须相同。根据这样的分析,一个二维数组也可以分解为多个一维数组,C语言允许这种分解。
例如,二维数组a[3][4]可分解为三个一维数组,它们的数组名分别为 a[0]、a[1]、a[2]。
这三个一维数组可以直接拿来使用。这三个一维数组都有 4 个元素,比如,一维数组 a[0] 的元素为 a[0][0]、a[0][1]、a[0][2]、a[0][3]。
其实,我们从编译器的角度,对上面的规则很好理解:
我们之所以可以省略二维数组定义的一维指定(就是可以定义为int a[][3] ),是因为我们在初始化时,第一维的长度[]是可以直接通过初始化确定的;但是作为第二维的长度[3],因为有了3这个长度,所以在赋值时可以“只对部分元素赋值,未赋值的元素自动取“零”值”。
你完全可以把这个作为一种规则来记住:
二维数组第一维长度可以省略后通过初始化来确定;第二维长度需要指定,同时可以对第二维只对部分元素赋值,未赋值的元素自动取“零”。 |
|