数组指针和指针数组的区别

指针数组:首先它是一个数组,每一个元素都是一个指针。

数组指针:首先它是一个指针,它指向一个数组。它是"指向数组的指针"的简称。

运算符的优先级关系:() > [] > *

数组指针(也称行指针)
例如:int (*p)[n];
根据优先级,先看( )内,p是一个指针,后面的[ ]又说明了p是一个指向数组的指针,由于前面的int,所以p是一个指向 int 类型数组的一个指针。

将二维数组赋给指针:

int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
p=a;         //将该二维数组的首地址赋给p
p++;         //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

所以数组指针也称指向一维数组的指针,亦称行指针。

指针数组
例如: int *p[n];
根据优先级,p先与[ ]结合,所以p是一个数组,再结合 *,表明数组里面的元素是指针,再加上int,说明p数组中的元素是int类型的指针。

将二维数组赋给指针数组:

int *p[3];
int a[3][4];
p++;              //该语句表示p数组指向下一个数组元素。for(i=0;i<3;i++)p[i]=a[i]
这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]所以要分别赋值。

在二维数组里面
a,&a,a[0],&a[0],&a[0][0]五个值是一样的,都指向二维数组的首地址(起始位置)。区别在于这五种表达方式的类型是不同的,以int a[2][3]举例:
a是二维数组名,是常量,存放着二维数组的首地址,类型为二维数组,sizeof(a)=24。
&a 二维数组a的(首)地址,本身是一个指针,sizeof(&a)=4,指针类型都为4。
a[0]指向二维数组中的第一行数组a[0][],类型是一维数组sizeof(a[0])=12。
&a[0]代表a[0]的地址,与一维数组名a[0]值相同,但本身是指针类型sizeof(&a[0])=4。
&a[0][0]表示二维数组中第一个元素的地址,指针类型sizeof(&a[0][0])=4。

A和&A之间的区别

分析如下代码:

int main()
{char a[5]={'A','B','C','D'};char (*p3)[5] = &a;char (*p4)[5] = a;return 0;
}

上面对p3 和p4 的使用,哪个正确呢?p3+1 的值会是什么?p4+1 的值又会是什么?毫无疑问,p3 和p4 都是数组指针,指向的是整个数组。&a 是整个数组的首地址,a是数组首元素的首地址,其值相同但意义不同。在C/C++里,赋值符号“=”号两边的数据类型必须是相同的,如果不同需要显示或隐式的类型转换。p3 这个定义的“=”号两边的数据类型完全一致,而p4 这个定义的“=”号两边的数据类型就不一致了。左边的类型是指向整个数组的指针,右边的数据类型是指向单个字符的指针。在Visual C++6.0 上给出如下警告:

warning C4047: 'initializing' : 'char (*)[5]' differs in levels of indirection from 'char *'。

这里给出了警告,可是由于&a 和a 的值一样,而变量作为右值时编译器只是取变量的值,所以运行并没有什么问题。虽然能运行,但不能这么用。

现在清楚了p3 和p4 都是指向整个数组的,那p3+1和p4+1的值就很好理解了。测试代码如下:

#include <iostream>
#include <cstdio>
using namespace std;int main()
{char a[5]={'a','b','c','d'};char (*p1)[5]= &a;char (*p2)[5]=(char (*)[5])a;printf("a = %p\n",&a);          //%p打印数组地址printf("a = %c\n",a[0]);printf("p1 = %c\n",**p1);printf("p2 = %p\n",*p2);printf("p1+1 = %p\n",*(p1+1));  //p1是数组指针,数组a的长度是5个字节,所以p1+1将指向a[0]向后移动5个字节的位置printf("p2+1 = %p\n",*(p2+1));  return 0;
}

结论:根据指针类型及所指对象,表示指针大小,每次加1,表示增加指针类型大小的字节。

另一个实例

#include <iostream>
#include <cstdio>
using namespace std;int main()
{int a[4]={1,2,3,4};int *ptr1=(int *)(&a+1);         //指向a数组后面的内存单元,&a+1表示向后移16个存储单元int *ptr2=(int *)(a+1);          //表示a的存储单元的地址增加一个字节printf("%d,%d",ptr1[-1],*ptr2);  //ptr1[-1]其实指向的是a数组的最后一个单元return 0;
}

其内存布局如下图:

参考:https://www.cnblogs.com/mq0036/p/3382732.html

C/C++数组指针和指针数组相关推荐

  1. C++ 笔记(27)— 指针变量、数组和指针、指针数组、数组指针、指针常量与常量指针

    1. 什么是指针变量? 指针变量是专门有一个变量来存放指针. int main(int argc, char *argv[]) {int a = 10;int *p = &a; //通过取地址 ...

  2. 关于C语言中的数组指针、指针数组以及二级指针

    概念解释 数组指针:首先它是一个指针,它指向一个数组,即指向数组的指针:在32 位系统下永远是占4 个字节,至于它指向的数组占多少字节,不知道.数组指针指向的是数组中的一个具体元素,而不是整个数组,所 ...

  3. 【C语言】数组指针与指针数组的区分与应用

    这里以一道C语言题--输出矩阵两个对角线上的数(二维数组)为例 7-57 输出矩阵两个对角线上的数(二维数组) (6 分) 编写程序,将数据输入一个n * n二维数组中,输出矩阵两个对角线上的数.假设 ...

  4. C++ 笔记(14)— 指针(指针声明、取地址、取值、new/delete、NULL指针、指针运算、指针数组、数组指针、指针传递给函数、从函数返回指针)

    1. 声明指针 指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址.就像其他变量或常量一样,您必须在使用指 针存储其他变量地址之前,对其进行声明. 指针变量声明的一般形式为: type * ...

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

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

  6. inline函数返回值_C++知识补充-指针,const,函数指针,指针数组,运算符重载

    嵌入式Linux:C++ 面试准备珍藏版本​zhuanlan.zhihu.com 明月照我心:123道c++笔试题汇总(含答案)​zhuanlan.zhihu.com 阿贵:常见C++笔试面试题整理​ ...

  7. C指针4:数组指针(指向数组的指针)

    先明确两个概念:(1和2是两个完全不一样的东西) 1.数组指针:如果一个指针指向了数组(该数组就是普通定义的数组),我们就称它为数组指针(Array Pointer).(1强调的是指针) 2.指针数组 ...

  8. extern数组与extern指针

    数组名代表了存放该数组的那块内存,它是这块内存的首地址.这就说明了数组名 是一个地址,而且,还是一个不可修改的常量,完整地说,就是一个地址常量.数组名 跟枚举常量一样,都属于符号常量.数组名 这个符号 ...

  9. c语言中的字节和元素,C语言指向数组元素的指针

    指向数组元素的指针和运算法则 所谓指向数组元素的指针,其本质还是变量的指针.因为数组中的每个元素,其实都可以直接看成是一个变量,所以指向数组元素的指针,也就是变量的指针. 指向数组元素的指针不难,但很 ...

  10. 用指针实现删除数组中小于10的数据

    <程序设计基础实训指导教程-c语言> ISBN 978-7-03-032846-5 p92 5.1.2 上级实训内容 [实训内容5]用指针实现删除数组中小于10的数据 正确程序已更新 正确 ...

最新文章

  1. PHP URL处理关键函数parse_url、parse_str与http_build_query
  2. 应用程序0xc0150002 错误
  3. ISA三向外围网络模板说明
  4. AppController
  5. 2014.7.26-7.29日广大网友的提问解答(答问题的第1个工作周)
  6. SpringBoot2.1.9 Mybatis由于@Mapper注解多数据源配置不生效问题
  7. 【CCF】 201604-1折点计数
  8. 宅男程序员给老婆的计算机课程之4:SQL vs NoSQL
  9. python sanic_Sanic框架安装与简单入门示例
  10. new file会创建文件吗_Python处理文件—os模块
  11. 计算机毕业设计源码分享双鱼林,计算机毕业课程设计论文源码-057双鱼林asp教务选课信息系统...
  12. Linux下编译安装qemu和libvirt
  13. activiti启动流程实例
  14. TypeScript笔记(1)——环境配置与第一个ts程序
  15. 最全iOS数据存储方法介绍:FMDB,SQLite3 ,Core Data,Plist,Preference偏好设置,NSKeyedArchiver归档...
  16. java 线程condition_(七)java多线程之Condition
  17. Allegro如何更改铜皮的网络操作指导
  18. Swift网络请求 - RXSwift + PromiseKit + Moya
  19. ESP32开发路程蓝牙篇——BLE(GATT),修改设备名称,添加characteristic,发送数据,接收数据
  20. U盘常见病毒或木马解决篇

热门文章

  1. C++ 析构函数设为虚函数的好处
  2. pycharm debug 断点调试
  3. 为什么说Prometheus是足以取代Zabbix的监控神器?
  4. 有理有据!为什么String选择数字31作为hashCode方法乘子?
  5. 在公司的微服务上搞破坏真是太开心了
  6. HTTP over QUIC重命名为“HTTP / 3”协议
  7. MongoDB 基础浅谈
  8. 直播预约 | 揭秘微信支付背后的数据库技术
  9. Paxos和Raft的前世今生
  10. PMP之项目质量管理---项目质量管理措施