如果,某个数组的维数不止一个,这样的数组被称为多维数组。
举例:
int one;
int onearray[2];
int twoarray[6][2];
int threarray[3][6][2];
四种数据类型的结构如上图,他们在内存中存储的顺序也是按照上图排序存储的。
如上图,数组中的元素是顺序存储的,多维数组的存储顺序是按照最右边的下表先变化的原则,称为行主续。
举例:
threarray[3][6][2]
存储顺序为:
0,1. 0,1. 0,1. 0,1. 0,1. 0,1.
0,1. 0,1. 0,1. 0,1. 0,1. 0,1.
0,1. 0,1. 0,1. 0,1. 0,1. 0,1.
其中0和1为下表序号。
二维数组:
int twoarray[6][2];
twoarray[6][2] =
{
{0,0},
{0,0},
{0,0},
{0,0},
{0,0},
{0,0},
};
三维数组:
threarray[3][6][2] =
{
{ {0,0},{0,0},{0,0},{0,0},{0,0},{0,0} },
{ {0,0},{0,0},{0,0},{0,0},{0,0},{0,0} },
{ {0,0},{0,0},{0,0},{0,0},{0,0},{0,0} }
};
指针和数组并不是相等的!牢记,在后面的博客中解释。
一维数组名的值是一个指针常量,它的类型是“指向数组元素类型的指针”,它指向数组的第一元素。多维数组也是类似的原理。
对于二维数组:
int twoarray[6][2];
twoarray[6][2] =
{
{0,0},
{0,0},
{0,0},
{0,0},
{0,0},
{0,0},
};
它是一个内含int数组的 数组,即它的第一维的元素实际上是另外一个数组。
twoarray的首元素是一个内含两个int值的数组,所以twoarray该数组名是这个内含两个int值的数组的 地址。
twoarray是该数组首元素的地址,它的值是指向它第一个元素的指针, 所以,twoarray(该数组名)是一个 指向
一个包含两个整形元素的数组的 指针。
&twoarray[0] 是区该二维数组首元素的地址, 所以,twoarray 和 &twoarray[0]的值应该是相同的!
twoarray[0]本身是 一个内含两个int类型值的数组,twoarray[0]是一个内含两个int类型值的数组的数组名。
因为数组名就是该数组首元素的地址,所以, twoarray[0]和&twoarray[0][0]的值应该是相同的!
由于这个整数twoarray[0][0]所在的数组twoarray[0]
和内含两个整数的数组twoarray[0]所在的数组twoarray都开始于同一个地址,所以twoarray[0]和twoarray值应该是相同的。
但是,注意twoarray[0]是一个内含两个整数的数组,所以它实际一个占用了一个int大小对象的地址。 twoarray是一个内含了6个
其中每个包含两个整形元素的数组 的数组,所以它是一个占用了2个int大小对象的地址!
当指针或地址加1,其值会增加对应类型大小的值,所以,twoarray+1和twoarray[0]+1得到的结果是不同的!
问题:地址怎么区分出占用了一个int大小还是2个int大小的?
总结:
对于以上二维数组,该数组的首元素是一个内含两个int值的数组。
twoarray[0]、twoarray[1]、…twoarray[5]本身是一个内含两个整数的数组;
所以twoarray[0]是 一个内含两个整数的数组的 首地址。
下表引用实际上只是间接访问表达式的一种伪装形式,在多维数组中也是如此。
举例:
int mul_array[3][5];
mul_array[1][3]
访问的元素如图:红框中,按内存排序和按行排序分别标出。
mul_array的类型是“指向包含5个整形元素数组的指针”,他的值是
如图:
mul_array + 1也是“指向包含10个整形元素数组的指针”,但他指向的是mul_array的下一行。
“+1” 的值是根据 “包含10个整形元素数组的长度”进行调整, 所以,表达式 *(mul_array + 1) 事实上表示了一个包含10个整形元素的子数组。
int array[10];
int* array_p = array;//正确
int mul_array[3][10];
int* mul_array_p = mul_array;//错误
第一个声明是合法的,它为一个整形数组分配内存,并把 array_p声明为一个指向整形的指针。
第二个声明是非法的,声明创建了多维数组 mul_array,创建了一个指向整形的指针mul_array_p,但对它的初始化是不正确的,因为mul_array不是一个指向整形的指针,而是一个指向整形数组的指针。
int (*p)[10];
下标的优先级高于间接访问,但是由于括号的存在,先执行的是间接访问,所以p是一个指针。接下来执行的是下标引用,所以p指向某种类型的数组,根据int可知,p是指向一个整形的数组,数组的每个元素都是整数。
所以在刚才的例子中,应该定义如下:
int mul_array[3][10];
int (* mul_array_p)[10] = mul_array;//正确
int* (p[10]);
int* p[10];
“[]”操作符的优先级高于 “*”操作符,所以括号也可以省略。
int (*pfun)(int);
int (*pfun[10])(int);
int (*(pfun[10]))(int);