指向数组的指针的理解

开发工具与关键技术:Visual Studio、C++
作者:张国军
撰写时间:2019年05月03日

数组和指针是两种不同的类型,数组具有确定数量的元素,而指针只是一个标量值。数组可以在某些情况下转换为指针,当数组名在表达式中使用时,编译器会把数组名转换为一个指针常量,是数组中的第一个元素的地址,类型就是数组元素的地址类型,如:
int a[5]={0,1,2,3,4};
数组名a若出现在表达式中,如int *p=a;那么它就转换为第一个元素的地址,等价于int p=&a[0];
再来一个:
int aa[2][5]={0,1,2,3,4, 5,6,7,8,9};
数组名aa若出现在表达式中,如int (
p)[5]=aa;那么它就转换为第一个元素的地址,等价于int (p)[5]=&aa[0];
但是int (
p)[5]=aa[0]; 这个就不对了,根据规则我们推一下就很明了了,aa[0]的类型是int [5],是一个元素数量为5的整型数组,就算转化,那么转化成的是数组(int [5])中第一个元素的地址&aa[0][0],类型是 int 。所以,要么是int (p)[5]=aa;要么是int (p)[5]=&aa[0];
只有在两种场合下,数组名并不用指针常量来表示–就是当数组名作为sizeof操作符或单目操作符&的操作数时,sizeof返回整个数组的长度,使用的是它的类型信息,而不是地址信息,不是指向数组的指针的长度。取一个数组名的地址所产生的是一个指向数组的指针,而不是指向某个指针常量值的指针。
如对数组a,&a表示的是指向数组a的指针,类型是int (
) [5],所以int p=&a;是不对的,因为右边是一个整形数组的指针int ()[5],而p是一个整形指针int
数组的sizeof问题会在下面中仔细讨论。
二、数组与指针的下标引用
int a[5]={0,1,2,3,4};
如a[3],用下标来访问数组a中的第三个元素,那么下标的本质是什么?本质就是这样的一个表达式:
(a+3),当然表达式中必须含有有效的数组名或指针变量。
其实a[3]和3[a]是等价的,因为他们被翻译成相同的表达式(顶多顺序不同而已),都是访问的数组a中的元素3。
指针当然也能用下标的形式了,如:int p=a; 那么p[3]就是(p+3),等同于3[p](不要邪恶。。。3P,3P),同样访问数组a中的元素3。
根据这一规则,我们还能写出更奇怪的表达式,如:
int aa[2][5]={0,1,2,3,4,5,6,7,8,9};
1[aa][2],这个看起来很别扭,首先 1[aa],就是(1+aa),那么1[aa][2]就是((1+aa)+2),也就是aa[1][2]。
1[2][aa],这个就不对了,因为前半部分1[2]是不符合要求的。
当然在实际中使用这样的表达式是没有意义的,除非就是不想让人很容易的看懂你的代码。
三、数组与指针的定义和声明
数组和指针的定义与声明必须保持一致,不能一个地方定义的是数组,然后再另一个地方声明为指针。
首先我们解释一下数组名的下标引用和指针的下标应用,它们是不完全相同的,从访问的方式来讲。
int a[5]={0,1,2,3,4};
int p=a;
对于a[3]和p[3]都会解析成
(a+3)和(p+3),但是实质是不一样的。
首先对于a[3],也就是(a+3):
(1)把数组名a代表的数组首地址和3相加,得到要访问数据的地址,这里注意,数组名a直接被编译成数组的首地址;
(2)访问这个地址,取出数据。
对于p[3],也就是(p+3):
(1)从p代表的地址单元里取出内容,也就是数组首地址,指针名p代表的是指针变量的存储地址,变量的地址单元里存放的才是数组的首地址;
(2)把取出的数组首地址和3相加,得到要访问的数据的地址;
(3)访问这个地址,取出数据。
下面给出一个例子来说明若定义和声明不一致带来的问题:
设test1.cpp中有如下定义:
char s[]=“abcdefg”;
test2.cpp中有如下声明:
extern char *s;
显然编译是没有问题的。
那么在test2.cpp中引用s[i]结果怎样呢?如s[3],是‘d’吗?好像是吧
下面我们对test2.cpp中的s[3]进行分析:
s的地址当然是由test1.cpp中的定义决定了,因为在定义时才分配内存空间的;
我们根据上面给出的指针下标引用的步骤进行计算
(1)从s代表的地址单元的取出内容(4个字节),这里实际上是数组s中的前4个元素,这个值是“abcd”,也就是16进制64636261h,到这一步应该就能看出来问题了;
(2)然后把取出的首地址和3相加,得到要访问的数据的地址64636261h+3,这个地址是未分配未定义的;
(3)取地址64636261h+3的内容,这个地址单元是未定义的,访问就会出错。
我们来看一下例子

#include <iostream>
int main() {int a[5] = {1,2,3,4,5};int * p=a;for (int i = 0; i < 5; i++){cout << *(p+i)<<endl;}return 0;
}


这是我们一个简单int型的数组跟指针,我们int类型的指针指向的是一维数组,我们可以通过指针进行输出值,但是我们需要的操作是进行解址操作(),当然我们也可以通过下标来进行输出数值。
指针的话我们可以通过
(p+i)进行查询我们数组里边的数值至于我们的i,应为数组的内存是连续的,所以我们需要查询下一个值的时候,我们只需要加上位移量就可以的到我们相对应的数值了。有一个值的注意的地方就是,当我们加的长度过长的时候我们所使用的那块内存不属于我们这个数值的时候,那么将会报错,所以我们使用的时候需要知道我们数组的长度。

#include <iostream>
int main() {int a[5] = {1,2,3,4,5};int * p=a;for (int i = 0; i < 5; i++){cout << a[i]<<endl;}return 0;
}


这个是我们下标继续输出的 结果和代码,从结果上我们可以看出并没有什么区别,所以我们
可以通过我们的指针或者下标方式对我们数组里边的值进行操作。
至于 各位需要用到什么方式去获得我们数组里边的值,那就看各位的需要了。
下边是我们指针指向我们的二维数组

#include <iostream>
int main() {int a[5][2] = {1,2,3,4,5,6,7,8,9,0};int * p=*a;for (int i = 0; i < 5; i++){for (int j = 0; j < 2; j++){cout << a[i][j]<<endl;}        }return 0;
}


这是我们二维数组使用下标方式进行输出。
当然他也是可以通过指针方式进行输出的,我这里呢就不给大家讲解了,需要大家自己去思考一下,
这是我对指向数组的指针的理解,如果大家有什么不同的想法呢可以一起分享,一起言论。

指向数组的指针的理解相关推荐

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

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

  2. 数组名与指向数组的指针之间的联系与区别【数据结构】

    我们遇到一个非常棘手的问题,这个问题就是,对于一堆数据来说,我们进行存储,放到一个指定的仓库当中,先前我们使用数组加加标的形式进行访问仓库当中的元素位置,但是呢,现在我们使用的是一个指针结构,指针指向 ...

  3. C语言数组指针(指向数组的指针)详解

    数组(Array)是一系列具有相同类型的数据的集合,每一份数据叫做一个数组元素(Element).数组中的所有元素在内存中是连续排列的,整个数组占用的是一块内存.以int arr[] = { 99, ...

  4. 深入浅出C语言:(三)C 语言数组指针(指向数组的指针)

    目录 一.C 语言数组指针(指向数组的指针) 二.C 语言字符串指针(指向字符串的指针) 三.C 语言指针数组(数组每个元素都是指针) 四.二维数组指针(指向二维数组的指针) 五.指针数组和二维数组指 ...

  5. 指向数组的指针与指向数组首元素的指针

    我的主力博客:半亩方塘 以下原创内容,转载请注明地址,欢迎对以下内容提供不同参考意见: 指向数组的指针与指向数组首元素的指针究竟有什么区别呢?有人说,这二者不是一回事么?它们就是同一个东西啊!然而,事 ...

  6. C语言 数组的指针和指向数组的指针变量

    一.回顾二维数组和多维数组的概念 int a[3][4];  //二维数组 int a[2][3]4];  //多维数组 二.指向多维数组的指针和指针变量的探究 可以把a看成是一个一维数组,这个一维数 ...

  7. 第五章 指向数组的指针

    讲到第五章了,数组两个字还离不开我们的左右,数组的内容也真多,另一方面也因为数组与指针的关系的确非常密切. 通常,对于int a[8][9]这个二维数组,我们可以这样定义一个指向它的指针: int ( ...

  8. C/C++指向指针的指针、指向数组的指针以及存放指针的数组

    关于指针这块,有段时间没有接触了(因为最近都是在使用java),感觉有点生疏了,昨天同学问了关于一个指针的问题,当时竟然卡住了,好吧,还是基础不够牢靠啊,突然觉得掌握了东西还是要以某种形式记录下来,光 ...

  9. C语言数组指针(指向数组的指针)

    数组(Array)是一系列具有相同类型的数据的集合,每一份数据叫做一个数组元素(Element).数组中的所有元素在内存中是连续排列的,整个数组占用的是一块内存.以int arr[] = { 99, ...

最新文章

  1. mysql多个字符串连接池_使用Coroutine\Channel实现一个简单的MySQL连接池
  2. QT5中实现多窗口切换,并从子窗口返回数据
  3. PL/SQL之JOB用法 (定时跑数据)
  4. 2万字详解,彻底讲透 全文搜索引擎 Elasticsearch
  5. matlab 过度曝光,MATLAB:补偿图像处理中的过度曝光/过饱和度
  6. 参考AWR中的Instance Activity Statistics 计算IOPS
  7. 1 二进制(glibc版)安装MySQL实现主从复制(亲测)
  8. HDU2002 计算球体积【入门】
  9. Java中的全局变量与局部变量
  10. 2020成人高考计算机基础知识题库,成人高考计算机考试全套题库
  11. 微信小程序简单论坛实现demo,供参考。
  12. 昂达v811升级到4.22d之后shell可以使用root权限操控文件系统
  13. 非线性光纤光学_进展 | 二维材料复合光纤实现超高非线性效应
  14. Tapestry 4.1.3学习心得
  15. 微分的定义和介绍习题
  16. 利用西瓜播放器(xgplayer)实现直播点播
  17. 模拟磁盘调度 课程设计(操作系统 C语言)
  18. (1)Kurento之WebRTC通信架构
  19. jboss下ejb简介
  20. Yahoo Programming Contest 2019 D - Ears

热门文章

  1. 打开计算机 访问不到d盘,电脑d盘打不开怎么办,教你电脑d盘打不开怎么办
  2. 皮尔森类似度(Pearson Similiarity)计算举例与数学特性和存在问题
  3. 纯JS打造移动端触屏滑动图片集
  4. 习题7-5 找鞍点 (20分)(函数调用解法:先找最大值后比较是否为最小值)
  5. 文件共享总结上篇-Windows之间文件共享
  6. ovo svm_反思我在OVO担任远程产品设计实习生的时间
  7. 离散数学期末考试必考知识点
  8. 从零开始学习React——(十二):React单项数据流和混用jQuery以及函数式编程
  9. Android SDK安装、环境变量配置
  10. 老九C++零基础学习(二)变量声明和使用