一维数组
int arr[] = {11, 22, 33, 44};
arr:首地址(第一个元素的地址)
一维数组与指针
int arr[] = {11, 22, 33, 44};
因为,arr表示的是首地址,等价于
int* p = arr; /* 为什么是整型的?因为arr地址处存储的是整数 */
而,当我们对指针进行运算时:
二维数组
二维数组在内存中是以一维数组的方式存储,分为两类:行优先存储和列优先存储
二维数组与指针
二维数组是以一维数组在内存中进行存储,这里我们讨论的是:行优先
因此,这个二维数组在内存中存放的格式是:9, 2, 6, 3, 3, 8, 7, 1, 5, 1, 6, 3
int arr[ROW][COL] = {
{9, 2, 6, 3},
{3, 8, 7, 1},
{5, 1, 6, 3}
};
那么arr表示的是谁的地址呢?
上图,我们发现arr的地址值和arr[0] 以及 arr[0][0]的地址相同,那么arr表示的是首元素arr[0][0]还是arr[0]呢?
arr表示的是arr[0],因为,若arr表示的是arr[0][0],那么我们可以对arr进行解引用:
然而实际情况却是报错,
因此,arr表示的是arr[0],而arr[0]是什么?一维数组
综上,arr表示的是arr[0]的地址,解引用*arr得到的是一维数组a[0]
正如上图所示,解引用*arr 等于a[0],即*arr等于[9,2,6,3],即一维数组
还记得一维数组与指针吗?
一维数组的数组名表示的是首元素的地址,解引用可得到首元素
graph LR
A[二维数组:数组名解引用]-->|得到的是:一维数组(第一行)|B[*arr = 【9, 2, 6, 3】]-->|一维数组:数组名解引用,可得到首元素|C[*(*arr)= 9]
总结
综上,一维数组的数组名是首元素的地址,对数组名解引用可以得到首元素**(*arr = 首元素)**;
二维数组的数组名是第一行所表示的一维数组的地址,对二维数组名第一次解引用得到的是第一行所表示的一维数组,即***arr = arr[0],第一次解引用得到的是一维数组,那么只需在解引用一次就可得到首元素,即*(*arr) = 首元素**(以此类推,三维数组需对数组名解引用三次才能得到首元素)
补充
我们可将二维数组,看作以下形式:
那么,二维数组的数组名a表示的是首元素的地址,首元素是啥?a[0];a[0]是啥?一维数组
那么,a + 1是什么?a[1];a + 2呢?a[2]……a[1]是啥?第二行所表示的一维数组;a[2]是啥?第三行表示的一维数组
判断以下方式是否正确
已知:
int arr[3][4];
问:
A.
int* p = a;
B.
int* p = a[0];
C.
int* p = &a[0][0];
前提:
A. 错误,因为a表示的是a[0],a + 1表示的是a[1],从a[0]到a[1]跨越了4个数据,即16字节,而int* p每次只跨越4个字节,不可能跨越16个字节的
B. 正确,a[0]是什么?一维数组;一维数组的什么?一维数组的首元素地址,因此,每次只跨越一个数据,4个字节,正确(一维数组的数组名即首元素的地址,a[0]表示一维数组,那么a[0]即首元素地址)
C. 正确,&a[0][0],首元素的地址,每次跨越4字节,正确
在数组中,若不能得到一个数据,那么返回的都是地址值;如:二维数组中a[0][0]得到的是首元素,即一个数组;而,a[0]不是,a[0]是一维数组,那么返回的是a[0]的地址值
打印二维数组
在二维数组中,数组名表示的不是首元素的地址,a[0]表示的才是首元素的地址