1、二维数组的地址
int a[3][4] = {{1,3,5,7},{9,11,13,15},{17,19,21,23}}
a是二维数组名
(数组的)名字 ==地址
(行) 父数组(名) = a 地址
(列) 子数组 (名 )= a[0] 一维数组{1,3,5,7}的名字
a[1] 一维数组{9,11,13,15}的名字
a[2] 一维数组{17,19,21,23}的名字
地址
//1 的值的地址 既可以叫做二维数组的首地址,也可以面向列的首地址
a +1 偏移了多少?到了9的地址, a +2 到了17 的地址 (偏移值很大,取决于一列当中有多少个元素)
a[0] +1 偏移了多少? 到了3的地址 a[0] +2 到了 5 的地址
(a[0]是第一个子数组的地址,同时是第一个子数组的名字
a[1]是第二个子数组的地址,同时是第二个子数组的名字
a[2]是第三个子数组的地址,同时是第三个子数组的名字)
如果 int arr{3} = [1,2,3]
int *p = arr;
*p = 1, *(p+0) = 1 , *(p+1) =2
所以在a[3][4] 中 a[0],*a 表示子数组的地址
验证一下
2、二维数组的地址写法应用
可以换一种写法
还有种写法
总结一下
第三行可以这么理解:
a[1] = *(a+1); 取内容a +1, 前面再加一个取地址,他两就抵消了
3、数组指针
(定义一个指针去访问二维数组)
第 6 行的 12个数的地址空间其实是连续的
既然地址空间是连续的,可以定义一个p,让 p等于12 个连续的数据 的第一个数据
(用一层循环也可以啦)
但是结果有点失去了二维数组的味道,
哪能不能把一维数组的p 指向数组名呢?
( int arr[3][4] = {{11,22,33,44},{12,13,15,16},{22,66,77,88}};是个二维数组
表示二维数组的地址,可以把二维数组的开头的元素的地址拿到手)
这样写指针有点不太匹配,
p =arr; 是一个面向于行的,它的元素每一项都是数组。
int *p 是面向单个整型数的
第7行的p ++ 和第6行的arr ++ 是两码事,
arr ++跳的是整个数组,而P++跳的是一个整形变量
你拿二者互等的时候,编译一定有警告或者错误的
运行是可以正常运行的,只不过会产生一些风险性的错误
能不能定义一个指针,让指针偏移的时候,也偏移对应大小的数组?
数组指针:定义一个指针,指向一个数组
int arr[3][4] = {{11,22,33,44},{12,13,15,16},{22,66,77,88}} 可以理解为三个指针
{11,22,33,44}一个指针 {12,13,15,16}另一个指针 {22,66,77,88}另一个指针
每一个指针 (地址)大小都一样
int(*p) 代表是一个指针
int (*p2)[4];
p2 =arr;
会发现没有报错
这时候 p2 的属性可以把它当作arr 来玩
也可以把数组名当成指针来用
包括p2 的偏移也能看出来
产生这样的原因是左值运算
人类的思想 先用p2,再用p2++, 可是printf对参数是从右面开始取的
分开写就好了
//数组指针才是真正等同于二维数组名
4、数组指针和二维数组的配合应用
练习:用函数分装的方式,输出二维数组任意行列的数
一般的步骤呢?
//提示用户输入行列值
//找出对应行列值的那个数
//打印出来
也可以稍微加点改动