指针与二维数组
上篇文章我们说了
指针数组相当于是一个二维数组
比如
#include<stdio.h>
int main(){
int a[] = {1,2,3};
int b[] = {4,5,6};
int *p1 = a,*p2 = b;
int *p[2] = {p1,p2};
printf("%d",*p[0]);
我们看这一段代码
首先定义了两个数组分别是ab
然后定义了两个指针分别指向a和b(这里的指向是指向其中第一个元素为了方便书写后面就不累述了)
然后创建一个指针数组p里面包含两个元素p1和p2
那么这个指针数组里就可以索引到
1 2 3
4 5 6这些数据
那么其实
1 2 3
4 5 6
这个是一个2 * 3的二维数组
这个时候就有人说了 你这个二维数组这么麻烦,有啥用
首先我们要知道二维数组比如下面这个啊
int a[][4] = {{1,2,3,4},{5,6,7,8}};
我们在创建二维数组的时候是可以省略行,但必须要固定列的
所以这个列是相等的。
而通过指针数组我们可以将指针指向不同长度的数组
比如
int a[] = {1,2,3};
int b[] = {4,5,6,7,8,9};
int *p1 = a,*p2 = b;
int *p[2] = {p1,p2};
printf("%d",*(p[1]+4));
这里就是定义的a和b的长度不同
但是仍可以通过*(p[1]+4)来访问b数组里的第5个元素而a里是不存在第五个元素的
}
二维数组的数组名
我们之前讲了一维数组的数组名是数组中第一个元素的地址
那么二维数组的数组名是什么呢?
我们来理下逻辑
int a[] = {1,2,3};
a代表的是1的地址,因为1是数组a中的第一个元素
int b[][3] = {{1,2,3},{4,5,6}};
那么这个二维数组中第一个元素是什么呢
或者我们换一个想法
我们刚刚讲了其实二维数组和指针数组有相似之处
那么一个指针数组
int *p[2] = {p1,p2};
这个指针数组p中,第一个元素就是一个p1对吧
那么p1是一个指针,那么第一个元素的地址就是指针的地址
我们再看向二维数组
int b[][3] = {{1,2,3},{4,5,6}};
那么这个第一个元素就是{1,2,3}这个数组,那么这个地址是什么呢
那就是这个数组的地址,
这个我们是不是之前学过,没错
我们再给数组指针赋值的时候就说了数组指针指向的就是数组的地址,
所以说
二维数组的数组名,其实是一个数组指针,是一个指向这个二维数组中第一行的一个
数组指针
当然可能讲到这里大家可能还是不怎么懂,我们讲完索引之后可能就好一些
关于这个通过数组名进行索引
我们先来证实一下上面的猜想是不是对的
看以下代码
#include<stdio.h>
int main(){
// 这里是创建了一个2*3的二维数组
int b[][3] = {{1,2,3},{4,5,6}};
// 这里是创建了一个数组指针指向b中的第一个数组的位置
int (*p)[3] = &b[0];
// 分别打印
printf("%d\n",b);
printf("%d",p);
}
这个的运行结果就是下图
可以看见啊这个的地址是一样的所以说,我们上述猜想是正确的,
然后再来讲索引
比如我们对二维数组的数组名取值是什么呢
int b[][3] = {{1,2,3},{4,5,6}};
比如这个数组
我们取*b得到的结果是什么呢?
没错应该就是b中第一个数组的数组名
而这个数组名是指向该数组中的第一个元素的指针
所以*b得到的还是一个地址,是第一个数组中第一个元素的地址
也就是在这里是1的地址
所以我们再加一个*就得到了1
也就是**b得到的就是1
int b[][3] = {{1,2,3},{4,5,6}};
printf("%d",**b);
依次我们可以发现其实二维数组数组名的使用其实就是数组指针的使用,如果还有不懂的可以回去看上一篇文章
红豆泥阿里嘎多!
void指针和NULL指针
关于这个就简单的提一下
首先当一个指针被定义成void类型时
我们都知道void是无类型,而我们在使用指针的调用时,
是根据指针的类型来确定空间的,所以如果一个指针被定义成void
在调用的时候应该先转成别的指针类型再取值
转换方法就是*int *char这种
然后就是NULL指针
首先我们要知道NULL时一个常量
他是一个指向空的一个指针,也就是地址
所以当我们定义一个指针
int *p;
p这个时候是没有被赋值的
这个时候对其取值也就是说*p得到的结果就是一个随机的地址
而如果定义
int *p = NULL;
这个时候再取值,得到的结果就不是地址了,而是空
今天的学习就到此为止了
@2022 5 3 ;
还是3円吧