说明:int (*p)[4] 和 int *p[4](数组指针和指针数组),如果你是一个初学者,也许当你看到这两个名词的时候,已经懵了。其实,只要你理解了其中的含义.这两个名词对你来说会相当简单并且很有趣,下面,我们就来深入探讨一下究竟什么是数组指针,什么是指针数组。

一.指针数组

1.前面我们已经学过数组了,比如说要创建一个一维整型数组,该怎么创建呢?应该是这样的:int arr[N];其中,arr是数组名,即变量名,N是你所创建的这个数组中的元素个数,而前面的int则是这些元素的类型。所以其实可以将它读作整型变量数组。那万一你所创建的数组元素不是整型和浮点型这些基本类型,而是一个指针类型呢?这就是指针数组了。

2.指针数组,首先它也是一个数组,只不过这个数组中的元素的类型为指针类型,举个例子:double *arr[4],这是一个指针数组,包含四个元素,其中每个元素都是double*类型的,简单来说,它就是一个用来存储指针的数组。用一个图来说明这个指针数组的内存布局:

3.既然指针数组是一个数组,那么它就应该有数组所应具有的一些特点。举个例子,对于double* p[4],p+1加的是数组的步长,即一个double*的大小,四个字节(注意:在32位机中,所有指针的大小都为4个字节)。而如果对数组名p进行取地址后,则&p+1加的是sizeof(p),即4*4 = 16个字节,即&p+1就跨过了整个数组。

示例:

  1 #include<stdio.h>
  2 int main()
  3 {
  4     double *p[4] = {NULL};
  5     printf("p  = %p\t",p);
  6     printf("p+1  = %p\n",p+1);
  7     printf("&p = %p\t",&p);
  8     printf("&p+1 = %p\n",&p+1);
  9     return 0;
 10 }

程序运行结果:

二.数组指针

1.指针相信大家都比较熟悉了,比如:int *p定义了一个指针p,该指针指向一个整型数据单元,如果对该指针执行加1操作,则加的是4个字节;又如char *q定义了一个指针q,该指针指向一个字符型的数据单元,如果对该指针执行加1操作,则实际上加的是1(个字节)。那么问题来了,万一要定义一个指针,它所指向的数据单元为一个一维数组怎么办呢?对他执行加1操作又能得到什么呢?这就是数组指针了。

2.数组指针,首先得明白它是一个指针,只不过这个指针指向的数据单元为一个数组,举个例子,现在有一个一维数组int arr[4];现在要定义一个数组指针来指向它,按照一般指针的理解,应该是这样的,int[4]* p;表示定义一个指针p,而该指针的类型为int[4]*型的,但这在编译器中是会报错的,没什么理由,语法规定。实际上对这个数组指针的定义应该是这样的:int (*p)[4] = arr;说实话,这样看着,笔者觉得挺别扭的,不过没办法,编译器就只认这个写法,不过这完全不影响我们按照第一种写法去理解数组指针的本质。

3.上面已经说了,数组指针实质就是一个指针,只不过其指向的类型与基本类型不同罢了。对于基本类型的指针,执行加1加的是指针指向数据类型的字节数,那么对于数组指针呢?显然加1加的也是指针指向数据类型的字节数,那么数组指针指向数据类型的大小怎么判断呢?举个例子:int(*p)[4],下面将通过一张内存数据图对此进行阐述:

如图:该指针里面存的是一个数组的首地址,只不过该指针的类型为int[4] *型,这就导致了该指针的步长为4*4 = 16个字节,所以对该指针执行加一操作,实际上加的是16个字节,即整个数组的大小。

  1 #include<stdio.h>
  2 int main()
  3 {
  4     int arr[4];
  5     int (*p)[4] = (int(*)[4])arr;
  6     printf("%p\t",p);
  7     printf("%p\n",p+1);
  8     return 0;
  9 }

程序运行结果:

4.数组指针与二维数组的关系是什么呢?首先要知道,二维数组 int arr[m][n] 可以想象成是具有m行,n列的一个数组矩阵,也可以想象成是有m个一维数组,其中每个一维数组里面又有n个int型的元素.那么是否可以用一个类型为int[n] *型的指针指向该二维数组来实现行间跳转访问呢?答案是肯定的!就拿上面例子来说,假如有一个二维数组int arr[m][n],则可以定义一个数组指针为:int (*p)[n] = arr(这里最好强转一下),然后用p对数组进行访问,由以上可讲可知,这里的p+1加的是n*4个字节,即加的是二维数组每行的字节数。

示例:

  1 #include<stdio.h>
  2 int main()
  3 {
  4     int arr[3][4];
  5     int (*p)[4] = (int(*)[4])arr;
  6     printf("%p\t",p);
  7     printf("%p\n",p+1);
  8     return 0;
  9 }
 10 

程序运行结果:

注意:二维数组的存储在内存中实际上是线性存储的,可以说任何数据在内存上的存储都是线性存储的,但这并不影响我们用二维的思维去理解它。

三.下面是一个数组指针当做二维数组名访问数组的示例,只是为了巩固与拓展一下以上,对于二维数组名的具体使用方式,在下次更新(后天)会详细介绍。这里就简单介绍一下,当把二维数组名赋给一个指针数组后,例如如下示例,则该指针就拥有了二维数组名访问二维数组的方式,比如在这里,p代表数组的首地址,由于其拥有了二维数组名的特性,则**p就是二维数组里的第一个元素,而*(*(p+i)+j)是二维数组第i行第j列的元素。

示例:

  1 #include<stdio.h>
  2 int main()
  3 {
  4     int arr[3][4];
  5     int count = 0;
  6     for(int i = 0;i<3;i++)
  7         for(int j = 0;j<4;j++)
  8             arr[i][j] = count++;
  9     for(int i = 0;i<3;i++)
 10     {
 11         for(int j = 0;j<4;j++)
 12             printf("%2d  ",arr[i][j]);
 13         putchar(10);
 14     }
 15     int (*p)[4] = (int(*)[4])arr;
 16     for(int i = 0;i<3;i++)
 17     {
 18         for(int j = 0;j<4;j++)
 19             printf("%2d  ",*(*(p+i)+j));
 20         putchar(10);
 21     }
 22     return 0;
 23 }

程序运行结果:

转载于:https://www.cnblogs.com/tuihou/p/9732425.html

(C/C++学习)6.数组指针和指针数组相关推荐

  1. 【C语言进阶深度学习记录】二十八 数组指针与指针数组的分析

    数组指针与指针数是非常重要的概念.面试中也是经常会被问到的 文章目录 1 数组的类型 1.1 定义数组的类型 2 数组指针 2.1 数组类型和数组指针的代码分析 3 指针数组 3.1 指针数组代码案例 ...

  2. 一维数组所有元素是否大于_【C语言】- 指向一维数组元素的指针!你今天学习了吗?...

    前面我们已经学习了指针,如果指针存储了某个变量的地址,我们就可以说指针指向这个变量.数组及其数组元素都占有存储空间,都有自己的地址,因此指针变量可以指向整个数组,也可以指向数组元素. 一.用指针指向一 ...

  3. Golang学习——数组指针和指针数组的区别

    Golang中数组指针和指针数组区别 一.数组指针 1.语法 2.实例 3.通过指针访问数组 二.指针数组 1.语法 2.实例 区别二者,字面上只看 后两个字即可: 数组指针 :它是一个指针,但是数据 ...

  4. 数组存储与指针学习笔记(三)指针与数组

    嵌入式C语言学习进阶系列文章 GUN C编译器拓展语法学习笔记(一)GNU C特殊语法部分详解 GUN C编译器拓展语法学习笔记(二)属性声明 GUN C编译器拓展语法学习笔记(三)内联函数.内建函数 ...

  5. Go 学习笔记(13)— 指针定义、指针特点、空指针、指针数组、指向指针的指针、指针作为函数入参

    1. 复合数据类型 Go 语言基本的复合数据类型有指针.数组.切片.字典.通道.结构和接口等.格式如下: * pointerType // 指针类型, [n]elementType // 数组类型, ...

  6. C语言学习笔记--预编译/宏定义/数组/参数传递/函数指针

    目录 预编译 值传递.指针传递.引用传递 数组 typedef 函数指针 预编译 预编译又叫预处理.预编译不是编译,而是编译前的处理.这个操作是在正式编译之前由系统自动完成的.#define 和 #i ...

  7. C语言深度剖析书籍学习记录 第四章 指针和数组

    p 称为指针变量,p 里存储的内存地址处的内存称为 p 所指向的内存. 指针变量 p 里存储的任何数据都将被当作地址来处理 一个基本的数据类型(包括结构体等自定义类型)加上"*" ...

  8. c语言数组宏定义标识符,C语言学习笔记--预编译/宏定义/数组/参数传递/函数指针...

    目录 预编译 值传递.指针传递.引用传递 数组 typedef 函数指针 预编译 预编译又叫预处理.预编译不是编译,而是编译前的处理.这个操作是在正式编译之前由系统自动完成的.#define 和 #i ...

  9. 翁恺老师C语言学习笔记(十)指针_指针与数组

    传入函数的数组成了什么? · 当我们向一段函数传入数组变量,参数接收到的是值,如果我们传入指针时,参数接收到的是也是值(一个地址): · 如果传入函数的是一个普通变量,它接收到的是一个值 · 如果传入 ...

最新文章

  1. 中文版GPT-3来了?智源、清华发布清源 CPM——以中文为核心的大规模预训练模型
  2. Openstack Paste.ini 文件详解
  3. Linux2.6内核--VFS层中和进程相关的数据结构
  4. java 新浪天气预报接口_根据新浪天气API获取各地天气状况(Java实现)
  5. JavaScript-JavaScript概述及简单使用
  6. Redis的zset有多牛?请把耳朵递过来
  7. 前端学习(1880)vue之电商管理系统电商系统之获取左侧菜单数据
  8. SpringCloud入门之Maven系统安装及配置
  9. 特斯拉AI Day首秀:FSD终极进化?AI超算Dojo、D1芯片、人形机器人亮相!
  10. 一步一步写算法(之排序二叉树)
  11. [Erlang危机](5.1.0)VM检测概述
  12. Jfree 数据可视化
  13. 工业机器人图册 索罗门采夫_机械手控制系统设计(完整图纸)
  14. api-String
  15. Elasticsearch中安装IK分词器
  16. 3.Anaconda安装python环境
  17. ubuntu下route命令详解
  18. Java NIO由浅入深(作者原创)
  19. 8.custom-links
  20. 编写一个完整的矩阵向量乘法的MPI编程代码

热门文章

  1. MongoDB在windows服务器安装部署及远程连接MongoDB
  2. Python流程控制语句
  3. nagios二次开发(一)---开发思想
  4. PHP curl 模拟登录
  5. asp.net performance
  6. Javascript调用OCX控件
  7. 关于Redis的数据迁移(三种方法)
  8. 一般编译器错误_Java程序员最容易犯的10个错误
  9. 16.PHP_Ajax模拟服务器登录验证
  10. Win64 驱动内核编程-24.64位驱动里内嵌汇编