数组的指针、指针数组以及指向指针的指针
考虑数组的指针的时候我们要同时考虑类型和维数这两个属性。换一句话,就是说一个数组排除在其中存储的数值,那么可以用类型和维数来位置表示他的种类。
一维数组
在c和c++中数组的指针就是数组的起始地址(也就第一个元素的地址),而且标准文档规定数组名代表数组的地址(这是地址数值层面的数组表示)。例如:
int a[10]; int *p;
p=&a[0]//和p=a是等价的。
因为a是数组名,所以他是该数组的地址,同时因为第一个元素为a[0],那么&a[0]也代表了该数组的地址。但是我们是不是就说一个数组名 和该数组的第一个元素的&运算是一回事呢?在一维的时候当时是的,但是在高维的时候,我们要考虑到维数给数组带来的影响。
a[10]是一个数组,a是数组名,它是一个包含10个int类型的数组类型,不是一般的指针变量噢!(虽然标准文档规定在c++中从int[]到 int*直接转换是可以的,在使用的时候似乎在函数的参数为指针的时候,我们将该数组名赋值没有任何异样),a代表数组的首地址,在数字层面和a[10] 的地址一样。这样我们就可以使用指针变量以及a来操作这个数组了。
所以我们要注意以下问题:
- p[i]和a[i]都是代表该数组的第i+1个元素;
- p+i和a+i代表了第i+1个元素的地址,所以我们也可以使用 *(p+I)和*(a+I)来引用对象元素;
- p+1不是对于指针数量上加一,而是表示从当前的位置跳过当前指针指向类型长度的空间,对于win32的int为4byte;
多维数组
对于二维数组a[4][6];由于数组名代表数组的起始地址,所以a(第一层)和第一个元素a[0][0]地址的数字是相同的,但是意义却是不同的。 对于该数组我们可以理解为:a的一维数组(第一层),它有四个元素a[0]、a[1]、a[2]、a[3](第二层),而每个元素又含有6个元素a[0] [0],a[0][1],a[0][2],a[0][3],a[0][4],a[0][5](第三层),…到此我们终于访问到了每个元素了,这个过程我们 经历了:a->a[0]->a[0][0];
整体来讲:a是一个4行5列的二维数组,a表示它指向的数组的首地址(第一个元素地址&a[0]),同时a[0]指向一行,它是这个行的名字 (和该行的第一个元素的首地址相同(第一个元素为地址&a[0][0]))。所以从数字角度说:a、a[0]、&a[0][0]是相同 的,但是他们所处的层次是不同的。
既然a代表二维数组,那么a+i就表示它的第i+1个元素*(a+i)的地址,而在二维数组中
*(a+i)又指向一个数组,*(a+i)+j表示这个数组的第j+1个元素的地址,所以要访问这个元素可以使用 *(*(a+i)+j)(也就是a[i][j])。
他们的示意图为(虚线代表不是实际存在的):
对照这个图,如下的一些说法都是正确的(对于a[4][6]):
- a是一个数组类型,*a指向一个数组;
- a+i指向一个数组;
- a、*a和&a[0][0]数值相同;
- a[i]+j和*(a+i)+j是同一个概念;
总结一下就是:我们对于二维指针a,他指向数组a[0,1,2,3],使用*,可以使他降级到第二层次,这样*a就指向了第一个真正的数组。对于其他的情况我们也可以采用相同的方式,对于其他维数和类型的数组我们可以采用相类似的思想。
说到指向数组的指针,我们还可以声明一个指针变量让它指向一个数组。例如:
int (*p)[5];
这时p就是一个指针,要指向一个含有5个int类型元素的数组,指向其他的就会出现问题。这个时候我们可以使用上面的什么东西来初始化呢?我们可以使用*a,*(a+1),a[2]等。原因很简单:我们在一个二维的数组中,那么表达方式有上面的相互类似的意义呢?只有 *a,*(a+1),a[2]等。
指针数组
一个指针数组是指一个数组中的每个元素都是一个指针,例如:
int *p[10];//而不能是int (*p)[10]
或者
char *p[10];
此时p是一个指针(数值上和&p[0]一样);
在前面有int t[10];
int * pt=t;//使用pt指向t
那么这里我们用什么指向int *t[10]中的t呢?我们要使用一个指针的指针:
int **pt=t;
这是因为:在int *t[10]中,每个元素是指针,那么同时t又指向这个数组,数组上和&t[0]相同,也就是指向t[0],指向一个指针变量,可以说是一个指针的指针了,所以自然要用
int **pt;
指针的指针
一个指针变量内部可以存储一个值,这个值是另外一个对象的地址,所以我们说一个指针变量可以指向一个普通变量,同样这个指针变量也有一个地址,也就是 说有一个东西可以指向这个指针变量,然后再通过这个指针变量指向这个对象。那么如何来指向这个指针变量呢?由于指针变量本身已经是一个指针了(右值),那 么我们这里就不能用一般的指针了,需要在指针上体现出来这些特点,我们需要定义指针的指针(二重指针)。
int *p1=&i; int**p2=&p1;
综合以上的所有点,下面是我们常常看到一些匹配(也是经常出错的地方):
int a[3],b[2][3],c,*d[3]; void fun1(int *p); void fun2(int (*p)[3]); void fun3(int **p); void fun4(int p[3]); void fun5(int p[]); void fun6(int p[2][3]); void fun7(int (&p)[3]);
函数 不会产生编译时刻的可能值(但逻辑上不一定都对)--这里我觉得应该是有效的值
函数 |
不会产生编译时刻的可能值(但逻辑上不一定都对) |
fun1 |
a, &a[i], *b ,b[i],&b[i][j] ,&c ,d[i] |
fun2 |
b,b+i,--(这里我觉得应该是*b,*(b+1),b[1]) |
fun3 |
d |
fun4 |
a, &a[i], *b ,b[i],&b[i][j] ,&c ,d[i] |
fun5 |
a, &a[i], *b ,b[i],&b[i][j] ,&c ,d[i] |
fun6 |
b |
fun7 |
a |
为什么可以有这样的搭配,原因如下:
- 对于fun1 fun4 fun 5: 在编译器看来fun1,fun4,fun5的声明是一样,在编译时候,编译器把数组的大小舍去不考虑,只考虑它是一个指针,也就是说有没有大小说明是一样的,所以三者的形式都是fun1的形式(其实只要提供了int*指针就可以了);
- 对于fun7 :以上的解释对于引用是不适用的,如果变量被声明为数组的引用,那么编译器就要考虑数组的大小了,那么必须和声明一模一样(所以fun7就只有a合适);
- 对于fun2:p是一个指向一个含有3个元素的数组,这样b和b+i正好合适,而a却不是(它是指向a[0]的,不是指向这个数组的);
- 对于fun3:p是一个指针的指针,而d指向d[0],同时d[0]又是一个指针,所以d就是一个指针的指针。但是b却不是(它是一个2*3的矩阵也就是年int [2][3]类型);
- 对于fun6,p是一个2*3的数组类型,和b恰好完全匹配;
数组的指针、指针数组以及指向指针的指针相关推荐
- 20返回指针的函数与指向函数的指针
一.返回指针的函数 指针也是C语言中的一种数据类型,因此一个函数的返回值肯定可以是指针类型的. 返回指针的函数的一般形式为:类型名 * 函数名(参数列表) 比如下面这个函数,返回一个指向char类型变 ...
- c/c++ 函数、常量、指针和数组的关系梳理
压力才有动力,15年中旬就要准备实习,学习复习学习复习学习复习学习复习--无限循环中,好记性不如烂笔头--从数组开始,为主干. c 的array由一系列的类型相同的元素构成,数组声明包括数组元素个数和 ...
- C语言深度剖析书籍学习记录 第四章 指针和数组
p 称为指针变量,p 里存储的内存地址处的内存称为 p 所指向的内存. 指针变量 p 里存储的任何数据都将被当作地址来处理 一个基本的数据类型(包括结构体等自定义类型)加上"*" ...
- c语言指针b 和b j,c语言精华 ------ 指针和数组
一.指针. 它的本质是地址的类型.在许多语言中根本就没有这个概念.但是它却正是C灵活,高效,在面向过程的时代所向披靡的原因所在.因为C的内存模型基本上对应了现在von Neumann(冯·诺伊曼)计算 ...
- C语言指针这一篇够了(一万二千字,包含指针与数组,函数指针等详解)
目录 零.前言 一.指针的定义 二.指针类型的意义 1.指针类型决定了指针解引用时一次访问几个字节. 2.指针类型决定了指针加减整数时的步长 三.野指针 1.未初始化的指针 2.指针的越界访问 3.指 ...
- 【C/C++学习】之七、指向函数的指针
什么是指向函数的指针 函数指针是指向函数的指针变量,不是指向对象的指针!函数指针本身应该是"指针变量": "在C语言中,函数本身不是变量,但可以定义指向函数的指针,这种指 ...
- 【C语言学习笔记】26. 指针(3)指向指针的指针、传递指针给函数
前言 指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链.通常,一个指针包含一个变量的地址.当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置. ...
- 【数据结构基础】指向函数的指针
文章目录 一.函数的指针 二.指向函数的指针变量 三.调用函数的两种方式 四.用指向函数的指针作函数参数(重点) 五.为什么要将指向函数的指针变量作为函数的形参(重点) 一.函数的指针 首先,函数名代 ...
- C指针8:二级指针(意思就是指向指针的指针)
指针可以指向一份普通类型的数据,例如 int.double.char 等,以下简称一级指针: 也可以指向一份指针类型的数据,例如 int *.double *.char * 等.以下简称二级指针:即如 ...
- C++基础之指向成员的指针
C++中指向成员的指针 一个类有两种基本的成员:函数成员和数据成员.同样的,指向成员的指针也有两种:指向函数成员的指针和指向数据成员的指针.后则其实并不常用,因为类一般是不含有公共数据成员的,仅当用在 ...
最新文章
- 【Linux学习笔记】 - 什么是Linux?
- javascript捕获ocx事件
- android读写文本文件,Android读写文件
- Java SecurityManager checkDelete()方法与示例
- java 不显示控制台_命令行启动java程序不显示控制台窗口
- java类成员方法(成员函数)的初步介绍
- centos修改磁盘uuid_如何修改linux磁盘的uuid
- 学习Python的利器:内置函数dir()和help()
- CS106A编程方法学二
- 新起点、新目标--获得MVP后的感悟
- es like模糊匹配_Elastic search模糊匹配,精确匹配显示在前
- matlab绘制三维机翼,三维机翼某一断面的压力系数X-Y曲线绘制——使用tecplot的extract功能...
- 了解腾讯云云支付CPay特性及应用场景
- 浏览器下载文件时文件名中文乱码问题
- 概率与数理统计学习总结四---连续型随机变量及其概率密度
- 智能搬运机器人系列之使用旭日X3派实现机器人防脱轨功能
- L39.linux命令每日一练 -- 第六章 文件备份与压缩命令 -- scp和rsync
- Plu2006即将开赛,参赛选手名单公布
- 用Bootstrap实现mansory网格瀑布流布局插件
- linux点用户输密码时就调回登录框,Linux系统登陆输入密码正确 闪回登陆界面
热门文章
- 用VISP+Opencv做相机到机械臂的标定
- java 又一次抛出异常 相关处理结果演示样例代码
- 求解二阶偏微分方程c语言,科学网—求解偏微分方程开源有限元软件deal.II学习--Step 3 - 亓欣波的博文...
- PHP_微信公众号开发(1)
- 关于移动硬盘故障:使用驱动器G:中的光盘之前需要将其格式化或者无法访问磁盘G:参数错误的解决办法
- autojs读取文字_Auto.js小白详细代码分析教程-如何阅读本文档 - Documentation
- NewstartHA 配置技巧
- 用 Vue 改造 Bootstrap,渐进提升项目框架[转]
- 机器学习损失函数 / 激活函数 / 优化算法 总览
- [经验技巧] 路由mini安装OpenWRT源的Transmission插件,实现PT下载(需SSH)