常见指针类型入门

常见指针类型入门

指针是C++中极其重要的概念,若是说某汪在华语乐坛占据了半壁江山,那么指针也是支撑C++众多高级特性的一双有力的大手。本文简要说明C++中指针的定义及指针类型的判断,其中指针类型的判断每每是初学者最大的障碍,但这也是最须要重点掌握的基础技能程序员

1、什么是指针

  1. 指针的定义

    从各类教科书上大同小异的定义来看,指针就是保存其余变量的地址的变量。要想弄懂这个定义,咱们须要先搞清楚两个概念:变量、变量的地址。编程

  2. 变量、变量的地址

(1)变量的引入

变量是用于存储某一数值的“容器”(“容器”这一词在C++和其余领域中是专业术语,这里只是用于比喻,不要把这个词当成对变量的术语,牢记!),咱们在计算机中编程时,整体来看都是“输入——计算——输出”这一套路,因此每每会有大量的数据,若是程序中所有的数据都是使用字面常量的方式来记录,那么先不说可实现性,光光是程序的编写和维护就是一件几乎不可能的事了,因此从BCPL和B语言以后(准确地说是C语言后),正式有了变量的概念。程序员只须要定义好某种类型的变量,就能够存储对应类型的数据,而不需再再像在无类型语言里那样关心数据在内存中是如何存储的了。数组

(2)逻辑上的内存模型

这里所说的内存模型是高级语言程序员脑中的内存模型,实际上并不存在;内存的物理模型不须要高级语言的初学者考虑,故不在此讨论
程序运行在内存中,数据和指令都加载进内存中(然而实际上并非这么理想,在以后的文章中我会再介绍操做系统对内存的管理),因此为了让访问内存的设备能准确地定位到某一处,内存的每一处都分配了一个惟一的数值,至关于身份证号,称做地址。内存地址是二进制的数值。32位机的寻址能力就是能在由32位标识的内存地址中进行定位,因此内存大小被限制在4GB。
地址这一词与人类社会的门牌号很像,人住在屋子里,而屋子有一个编号,人看做数据,屋子就是存储“人”这一类型的变量,而门牌号就是变量的地址。函数

  1. 指针的做用

    看了以上这么多的文字,那么指针的类比概念也很好理解了,不过到此咱们须要回答一个问题:为何须要指针?经过指针来操做变量仍是一个二级的操做,这不会显得很麻烦吗?操作系统

是的,经过指针咱们确实比直接操做变量多作了工做,但偏偏就是指针,也给了程序员直接操做内存的机会,由于直接操做内存比操做变量在时间上要快上不少,这也是为何C++程序运行的效率高的缘由之一。指针

  1. 指针的类型

    指针(pointer)的全名实际上是指针变量,也就是说指针也是变量。既然是变量,那么很天然的也就有类型这一问题。C++是强类型的静态语言,某一种类型的变量就只能存储其对应类型的数据,指针也不例外。一般,当某一类型指针保存着其对应类型的地址时,咱们说“这个指针指向了那个变量”。code


2、指针的类型

正文从这开始。
把指针考虑成变量,因此咱们从最基本的变量(以整型为例)的定义开始分析。内存

  • int p;数学

p是一个整型变量。入门

  • int *p;

p是一个指向整型变量的指针。

  • int p[SIZE];

p是一个数组,数组中有SIZE个元素,每一个元素都是整型。

  • int *p[SIZE];

从这里开始变得有趣了
对于这种“复杂”类型的定义,有一种方法是从中间开始读,根据运算符优先级向两边扩展。
p是一个数组(先与定义数组的下标运算符结合,由于下标运算符[]的优先级高于解引用运算符*),数组中有SIZE个元素,而后与*结合,数组中的元素都是指针,最后看int,即指针指向int。因此,把以上的分析过程连起来,就是,p是一个由SIZE个指向整型的指针构成的数组。

  • int (*p)[SIZE];

这里咱们会开始简单看到()运算符的其中一个做用
首先,从p开始寻找优先级比*高的运算符——是的,()在这里的意义和数学中的小括号是同样的,都是用于强行改变运算优先级的运算符。因此,由于有(),p先与*结合,p是一个指针,而后再与[]结合,p这个指针指向一个有SIZE个元素的数组,最后,看int,即,p是一个指向由SIZE个整型元素构成的数组的指针。

  • int p(int);

这里就是()的另外一个做用
这里的()是函数调用运算符,()内写清了参数列表,因此,p是一个函数,函数有一个整型变量的参数,函数返回值为整型。

  • int p(int, int *, int);

分析过程同上一点,直接给出结果。
p是一个函数,有三个参数,依次为整型、指向整型的指针和整型,返回值为整型。

  • int **p;

C++中没有**这种的运算符,因此这种写法是等同于int *(*p);的。
其表示,p是一个指针,指向了一个指针变量,且被p指向的那个指针指向整型。
这种指针称做二级指针,相似的,还有多级指针,但在实际编写程序时,二级指针的使用已经比较少了,多级指针更是几乎(不表明没有用处)不会使用,因此初学者没必要考虑多级指针。

  • int (*p)(int *, int);

p是一个指针,指向了一个函数,这个函数的参数列表为(int *, int),返回值为int
这里的p,咱们就称之为函数指针,由于它指向了函数。函数指针的概念须要实际练习几回才能初步掌握。

  • void (*p[SIZE])(int *, int);

这种复杂程度的类型定义是程序中常常见到的,因此一点一点地来分析。
p先与[]结合,说明p是一个数组;再与左侧的*结合,说明数组里的元素都是指针;以后与右侧的函数调用运算符()结合,那些指针指向的函数的参数依次为(int *, int),返回值类型为void。因此,再整理一下刚刚的分析:
p是一个由SIZE个元素构成的数组,每一个元素都是函数指针,其指向的函数的参数依次为指向整型的指针、整型,返回值类型为void
这种类型要求重点掌握。

  • int *(*p(int))[SIZE];

这种类型的能够先跳过,在确认了掌握了上面讲述的全部定义后再来尝试理解。
从p开始分析,先与()结合,说明p是一个函数;而后进入到参数列表中,发现这个函数的参数只一个int;再看p左侧的*,说明这个函数的返回值是一个指针;以后到外层(这里外层的()是为了强制改变优先级),先与[]结合,说明函数返回的指针指向的是一个数组;再与左面的*结合,说明指向的数组中的元素都是指针;最后与int结合,说明数组中的元素指向整型。
因此,p是一个参数为一个int、且返回一个指向由SIZE个int *构成的数组的的指针的函数。

这里思考,若是去掉最外层的`()`,即改成以下:
    `int **p(int)[SIZE];`
    会是什么结果?为何?欢迎在以后的讨论区发表意见。

3、结语

经常使用的指针类型(或者直接说是类型)定义大多都是如上类型的变种,固然会有更复杂的,不过再复杂的均可以用上述的方法来进行分析。

相关文章
相关标签/搜索