😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍C语言多级指针、多维数组🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭
本文未经允许,不得转发!!!
🎄一、概述
多维数组与多级指针也是初学者感觉迷糊的一个地方。超过二维的数组和超过二级的指针其实并不多用。如果能弄明白二维数组与二级指针,那二维以上的也不是什么问题了。所以本文重点讨论二维数组与二级指针。
🎄二、二级指针
✨2.1 二级指针的本质
在前面的文章 C指针详解 中从4个方面来认识指针,知道指针本质上就是一个4个字节(32位系统) 或 8个字节(64位系统) 的内存块,其里面存放的值都会被编译器当作内存地址
来处理。
例如,下面语句:
char c = 'A';
char *p2 = &c;
可以用下图来表示,32系统分配一个4个字节的内存空间,命名为p2,里面存放了变量c的地址。
清楚了指针的本质之后,我们再看看二级指针,二级指针本质上也是一个4个字节(32位系统) 或 8个字节(64位系统) 的内存块,其里面存放的值也会被编译器当作内存地址
来处理。不同的是,二级指针里面存放的是一级指针的内存地址
。
例如,下面语句,p是二级指针,其内容里存放了指针p2的地址:
char c = 'A';
char *p2 = &c;
char **p = &p2;
记住:一级指针保存的是数据的地址,二级指针保存的是一级指针的地址。
✨2.1 二级指针的使用
使用*
对一个内地址解引用,就可以得到该内存地址的值。
二级指针保存的是一级指针的地址,对二级指针的值解引用,就得到一级指针的值,再对一级指针解引用才得到数据的值。
关于二级指针的使用,我们需要很清楚知道一级指针的地址
、数据的地址
、数据
,这三个要怎样去表示,看例子2.2.1:
#include <stdio.h>
int main()
{
char c = 'A';
char *p2 = &c;
char **p = &p2;
printf("一级指针地址: %p %p\n",p, &p2);
printf("数据地址: %p %p\n",*p, p2);
printf("数据: %c %c\n",**p, *p2);
}
🎄三、二维数组
✨3.1 二维数组的本质
看了前面文章 C语言数组详解(经典,超详细) ,我们清楚数组的本质是一段连续的内存空间,可以存储除了函数之外的任何数据。
例如:下面代码
char a[3];
在内存中的存储就类似于下图:
二维数组,本质上也是一段连续的存储空间。与一维数组不同的是,一维数组的数组元素是除了数组之外的其他类型,而二维数组的数组元素是一个数组类型。
例如:下面代码
char a[3][4];
在内存中的存储就类似于下图,先看a[3]
是一个数组,它有三个元素 ,每个元素都是一个数组类型的;这个数组类型有4个元素,每个元素是char
类型:
也就是说,二维数组的本质也是一段线性的连续的存储空间,其内存结构先按照第一维度的元素个数,将整个数组内存空间分割为若干份(第一维度元素个数);再将每个份按照第二维度的元素个数分割为若干份(第二维度的元素个数)。
✨3.2 二维数组的使用
以char a[3][4];
为例,a、a[0]、a[0][0]分别表示什么?
前面文章讲过,一维数组的数组名作为右值时,代表了数组首个元素的地址。同样的,二维数组或者多维数组,其数组名也表示该数组第一维度的首个元素的地址。以char a[3][4];
为例,数组名a
的地址值会等于 &a[0]
。数组名a
做右值使用时,可以当成一个常量指针,指针类型是char *[4]
,所指向的类型是char [4]
,所以±1
,会等同于±sizeof(char [4])
个字节。
那a[0]
又表示什么,以char a[3][4];
为例,这里的a[0]
作为右值使用时,相当于第二维度数组的数组名。所以 a[0]
地址值会等于&a[0][0]
;a[1]
地址值会等于&a[1][0]
。a[0]
做右值使用时,也可以当成一个常量指针,指针类型是char *
,所指向的类型是char
,所以±1
,会等同于±sizeof(char)
个字节。
a[0][0]
在这个例子中,是一个字符值了。类型是char
。
a[0]、a[0][0],还可以分别用*a
、**a
来表示。
看例子3.2.1:
#include <stdio.h>
int main()
{
char a[3][4]={"abc","def","ghi"};
printf("a=%p a[0]=%p a[0][0]=%c\n",a,a[0],a[0][0]);
printf("a=%p &a[0]=%p \n",a,&a[0]);
printf("a[0]=%p &a[0][0]=%p a[1]=%p &a[1][0]=%p\n",a[0],&a[0][0],a[1],&a[1][0]);
printf("a+1=%p %lu a[0]+1=%p %lu\n",a+1, (unsigned long)a+sizeof(char [4]), a[0]+1, (unsigned long)a[0]+sizeof(char));
printf("a[0]=%p *a=%p a[0][0]=%c **a=%c \n", a[0], *a, a[0][0], **a);
}
运行结果:
🎄四、多级指针
二级以上的指针很少用,写了几年代码了,从来没见过,但这里还是聊一聊。
遇到多级指针,我们还是要从其本质来理解,无论多少级的指针,在编译器看来都是一个4字节(32位系统)或8字节(64位系统)的一块内存,里面放着一个内存地址值。
看例子4.1:
#include <stdio.h>
int main()
{
char c = 'c';
char *pc = &c;
char **ppc = &pc;
char ***pppc = &ppc;
char ****ppppc= &pppc;
printf("ppppc=%p, pppc=%p, ppc=%p, pc=%p \n",ppppc, pppc, ppc, pc);
printf("****ppppc=%c c=%c\n", ****ppppc, c);
return 0;
}
只要清楚多级指针的本质,结合下面几句话就不那么模糊了。
四级指针存放的是三级指针的地址;
三级指针存放的是二级指针的地址;
二级指针存放的是一级指针的地址;
一级指针存放的是数据的地址;
🎄五、多维数组
二维数组以上的多维数组也很罕见。
不管多少维的数组,本质上都是一段连续的内存空间。然后把它每个维度单独当成一个数组去看待就好理解了。
例如:int a[3][4][5];
- 第一维度:数组名a,有3个元素a[0]、a[1]、a[2],每个元素类型是
int [4][5]
; - 第二维度:以
a[1]
为代表来看,数组名是a[1]
,有4个元素a[1][0]、a[1][1]、a[1][2]、a[1][3],每个元素类型是int [5]
; - 第二维度:以
a[1][2]
为代表来看,数组名是a[1][2]
,有5个元素a[1][2][0]、a[1][2][1]、a[1][2][2]、a[1][2][3]、a[1][2][4],每个元素类型是int
;
🎄六、总结
👉本文介绍C语言的二级指针、二维数组、多级指针、多维数组。
确实写完都有点懵了,有看见错误的,欢迎指正,这个主题确实容易错。
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁