在正式学习指针的进阶之前,我们先回顾一下指针的初阶的学习学到了哪些内容:
1.指针就是一个用来储存地址的变量,一个地址指向一个唯一的内存空间.
2.指针的大小固定是4个字节(32位平台)和8个字节(64位平台)。
3.指针的类型决定了指针+-整数的步长,比如:char型指针+1访问1个字节;int型指针+1访问4个字节。
接下来我们就开始 学习更高级的指针吧!
1. 字符指针
在指针的类型中我们知道有一种指针类型为字符指针 char* ;
我相信大部分同学都能看懂上面这个代码,那接下来看看下面的这个代码。这里我先提一个问题:
这里是把字符串放到pstr指针里面去了吗?
答案是:并没有将字符串放到pstr这个指针之中,而是将该字符串的首个字母的地址放到了pstr指针之中了。
我们将pstr中的地址和字符串中的地址拿出来比较也是可以看出来其中的关系:
这是一个面试题:
请你思考一下这里的输出结果:
这里的输出结果是 :
这里的str1和str2分别是两个字符数组,当它们在使用是,系统分别给他们开辟了两个不同的内存空间,所以说它们的地址也是不相同的;然而str3和str4是两个字符指针,他们虽然名字不相同,但是他们都是指向‘h’这个内存空间。所以他们的地址是相同的。
2.指针数组
指针数组是一个存放指针的数组。
3.数组指针
3.1数组指针的定义
首先,请问数组指针到底是数组?还是指针?
答案是:指针。
我们已经熟悉:
整形指针: int * pint; 能够指向整形数据的指针。
浮点型指针: float * pf; 能够指向浮点型数据的指针。
那数组指针应该是:能够指向数组的指针。
下面代码哪个是数组指针?
p1先和[]结合是一个数组,然后在和*结合,代表的是存放指针的数组;
指针数组存放的是指针变量的集合。换句话说,它是一个数组,其中的每个元素都是指向某种类型数据的指针。这意味着指针数组中的每个元素都存储着一个地址,这个地址指向内存中的某个位置,通常是另一个变量或数据结构的地址
然而p2先与*结合代表的是一个指针,然后再与[]结合,代表的是一个数组指针。
数组指针存放的是数组的内存地址,也就是数组的第一个元素的地址。换句话说,数组指针指向数组的起始位置。
3.2&数组名VS数组名
对于下面的数组:
&arr和arr分别代表的是啥?
我们知道arr是数组名,数组名表示数组首元素的地址。
那&arr数组名到底是啥?
我们看一段代码:
它的结果是:
可见数组名和&数组名打印的地址是一样的。
难道两个是一样的吗?
我们再看一段代码:
它打印的结果是:
虽然在上一个代码中&arr和arr打印出来的结果是相同的,但代表的意义是不同的,&arr是整个数组的地址,所以&arr+1是跳过了一个数组的大小,也就是40个字节的大小;
而arr是数组的首地址,也是第一个数组的地址(arr[0]),arr+1访问的是上一个数组的下一个数组的地址(arr[1]),所以他们相差4个字节,也就是一个整形的大小。
这里可能会有一点绕,要细细品味一下
3.3 数组指针的使用
那数组指针是怎么使用的呢?
既然数组指针指向的是数组,那数组指针中存放的应该是数组的地址。
看代码:
一个数组指针的使用:
4. 函 数 指 针
首 先 看 一 段 代 码:
输出结果:
5. 函数指针数组
数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组, 比如:
那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?
答案是:parr1 parr1 先和 [] 结合,说明 parr1是数组,数组的内容是什么呢? 是 int (*)() 类型的函数指针。 函数指针数组的用途:转移表
例子:(计算器)
6. 指向函数指针数组的指针
指向函数指针数组的指针是一个 指针 指针指向一个 数组 ,数组的元素都是 函数指针 ;
用法如下:
7. 回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当 这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调 用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
首先演示一下qsort函数的使用:
8.总结:数组名的意义
1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址。