• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > 图文详解c/c++中的多级指针与多维数组

图文详解c/c++中的多级指针与多维数组

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了六十四卦图文详解,周易64卦图文详解,无线充电原理图文详解,科目二图文详解,地理图文详解等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

前言

首先先声明一些常识,如果你对这些常识还不理解,请先去弥补一下基础知识:

     1、实际上并不存在多维数组,所谓的多维数组本质上是用一维数组模拟的。

     2、数组名是一个常量(意味着不允许对其进行赋值操作),其代表数组首元素的首地址。

     3、数组与指针的关系是因为数组下标操作符[],比如,int a[3][2]相当于*(*(a+3)+2) 。

     4、指针是一种变量,也具有类型,其占用内存空间大小和系统有关,一般32位系统下,sizeof(指针变量)=4。

     5、指针可以进行加减算术运算,加减的基本单位是sizeof(指针所指向的数据类型)。

     6、对数组的数组名进行取地址(&)操作,其类型为整个数组类型。

     7、对数组的数组名进行sizeof运算符操作,其值为整个数组的大小(以字节为单位)。

     8、数组作为函数形参时会退化为指针。

 一、一维数组与数组指针

      假如有一维数组如下:

 char a[3];
</div>

      该数组一共有3个元素,元素的类型为char,如果想定义一个指针指向该数组,也就是如果想把数组名a赋值给一个指针变量,那么该指针变量的类型应该是什么呢?前文说过,一个数组的数组名代表其首元素的首地址,也就是相当于&a[0],而a[0]的类型为char,因此&a[0]类型为char *,因此,可以定义如下的指针变量: 

 char * p = a;//相当于char * p = &a[0]
</div>

      以上文字可用如下内存模型图表示。

 

      大家都应该知道,a和&a[0]代表的都是数组首元素的首地址,而如果你将&a的值打印出来,会发现该值也等于数组首元素的首地址。请注意我这里的措辞,也就是说,&a虽然在数值上也等于数组首元素首地址的值,但是其类型并不是数组首元素首地址类型,也就是char *p = &a是错误的。

      前文第6条常识已经说过,对数组名进行取地址操作,其类型为整个数组,因此,&a的类型是char (*)[3],所以正确的赋值方式如下:

 char (*p)[3] = &a;
</div>

      注:很多人对类似于a+1,&a+1,&a[0]+1,sizeof(a),sizeof(&a)等感到迷惑,其实只要搞清楚指针的类型就可以迎刃而解。比如在面对a+1和&a+1的区别时,由于a表示数组首元素首地址,其类型为char *,因此a+1相当于数组首地址值+sizeof(char);而&a的类型为char (*)[3],代表整个数组,因此&a+1相当于数组首地址值+sizeof(a)。(sizeof(a)代表整个数组大小,前文第7条说明,但是无论数组大小如何,sizeof(&a)永远等于一个指针变量占用空间的大小,具体与系统平台有关)

二、二维数组与数组指针

      假如有如下二维数组:

 char a[3][2];
</div>

      由于实际上并不存在多维数组,因此,可以将a[3][2]看成是一个具有3个元素的一维数组,只是这三个元素分别又是一个一维数组。实际上,在内存中,该数组的确是按照一维数组的形式存储的,存储顺序为(低地址在前):a[0][0]、a[0][1]、a[1][0]、a[1][1]、a[2][0]、a[2][1]。(此种方式也不是绝对,也有按列优先存储的模式)

      为了方便理解,我画了一张逻辑上的内存图,之所以说是逻辑上的,是因为该图只是便于理解,并不是数组在内存中实际的存储模型(实际模型为前文所述)。

    

      如上图所示,我们可以将数组分成两个维度来看,首先是第一维,将a[3][2]看成一个具有三个元素的一维数组,元素分别为:a[0]、a[1]、a[2],其中,a[0]、a[1]、a[2]又分别是一个具有两个元素的一维数组(元素类型为char)。从第二个维度看,此处可以将a[0]、a[1]、a[2]看成自己代表”第二维”数组的数组名,以a[0]为例,a[0](数组名)代表的一维数组是一个具有两个char类型元素的数组,而a[0]是这个数组的数组名(代表数组首元素首地址),因此a[0]类型为char *,同理a[1]和a[2]类型都是char *。而a是第一维数组的数组名,代表首元素首地址,而首元素是一个具有两个char类型元素的一维数组,因此a就是一个指向具有两个char类型元素数组的数组指针,也就是char(*)[2]。

     也就是说,如下的赋值是正确的:

 char (*p)[2] = a;//a为第一维数组的数组名,类型为char (*)[2]

 char * p = a[0];//a[0]维第二维数组的数组名,类型为char *
</div>

      同样,对a取地址操作代表整个数组的首地址,类型为数组类型(请允许我暂且这么称呼),也就是char (*)[3][2],所以如下赋值是正确的: 

 char (*p)[3][2] = &a;
</div>

三、三维数组与数组指针

     假设有三维数组:

 char a[3][2][2];
</div>

     同样,为了便于理解,特意画了如下的逻辑内存图。分析方法和二维数组类似,首先,从第一维角度看过去,a[3][2][2]是一个具有三个元素a[0]、a[1]、a[2]的一维数组,只是这三个元素分别又是一个"二维"数组,a作为第一维数组的数组名,代表数组首元素的首地址,也就是一个指向一个二维数组的数组指针,其类型为char (*)[2][2]。从第二维角度看过去,a[0]、a[1]、a[2]分别是第二维数组的数组名,代表第二维数组的首元素的首地址,也就是一个指向一维数组的数组指针,类型为char(*)[2];同理,从第三维角度看过去,a[0][0]、a[0][1]、a[1][0]、a[1][1]、a[2][0]、a[2][1]又分别是第三维数组的数组名,代表第三维数组的首元素的首地址,也就是一个指向char类型的指针,类型为char *。

            由上可知,以下的赋值是正确的:

  char (*p)[3][2][2] = &a;//对数组名取地址类型为整个数组
  char (*p)[2][2] = a;
  char (*p) [2] = a[0];//或者a[1]、a[2]
  char *p = a[0][0];//或者a[0][1]、a[1][0]...
</div>

四:多级指针

      所谓的多级指针,就是一个指向指针的指针,比如:

  char *p = "my name is chenyang.";

  char **pp = &p;//二级指针

  char ***ppp = &pp;//三级指针
</div>

      假设以上语句都位于函数体内,则可以使用下面的简化图来表达多级指针之间的指向关系。

     

         多级指针通常用来作为函数的形参,比如常见的main函数声明如下:

 int main(int argc,char ** argv)
</div>

         因为当数组用作函数的形参的时候,会退化为指针来处理,所以上面的形式和下面是一样的。

 int mian(int argc,char* argv[]) 
</div>

         argv用于接收用户输入的命令参数,这些参数会以字符串数组的形式传入,类似于:

 char * parm[] = {"parm1","parm2","parm3","parm4"};//模拟用户传入的参数

 main(sizeof(parm)/sizeof(char *),parm);//模拟调用main函数,实际中main函数是由入口函数调用的(glibc中的入口函数默认为_start)
</div>

         多级指针的另一种常见用法是,假设用户想调用一个函数分配一段内存,那么分配的内存地址可以有两种方式拿到:第一种是通过函数的返回值,该种方式的函数声明如下:

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 图文详解c/c++中的多级指针与多维数组

相关文章

  • 2017-05-28c语言指针之二级指针示例
  • 2022-04-30C语言数据类型转换(自动类型转换+强制类型转换)
  • 2017-05-28浅析C/C++中的可变参数与默认参数
  • 2017-05-28vc中使用SendMessage自定义消息函数
  • 2017-05-28C语言编程中实现二分查找的简单入门实例
  • 2017-05-28c++遍历lua table示例
  • 2017-05-28学习C语言要掌握的几个库
  • 2017-10-15ST17H26移植软时钟代码
  • 2017-05-28在C++中反射调用.NET的方法(三)
  • 2017-05-28C++实现简单的职工管理系统实训代码

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C语言 数与串之间转换的方法
    • 深入全排列算法及其实现方法
    • c语言实现二叉查找树实例方法
    • 浅谈2路插入排序算法及其简单实现
    • C++ 中实现把EXCEL的数据导入数据库(ACCESS、MSSQL等)实例代码
    • c++中map的基本用法和嵌套用法实例分析
    • Find K-th Smallest Pair Distance:查找数组元素中差值第K大的两个元素的差值
    • 详解C++编程中对于函数的基本使用
    • C++事件处理中__event与__raise关键字的用法讲解
    • 简单比较C语言中的execl()函数与execlp()函数

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有