从 int*
和 int
说起
“int**
是什么”这个问题其实不难。
咱们能够递归剖析,先看下 int*
是什么,嗯?如同还能够持续递归到 int
咱们都晓得,int
是 C 的根底数据类型 整型
,而多了个 *
的 int*
是 指向整型变量的指针
,那么 int**
是什么就不言自明了,列个表:
C 语法 | 释义 |
---|---|
int |
整型 |
int* |
指向 整型 的指针 |
int** |
指向 指向整型的指针 的指针 |
看到这里,你对 int**
应该有了个初步的意识,但你可能感觉有点绕,没关系,上面咱们写一段代码看看:
#include <stdio.h>
int main()
{
int i = 418;
int* pi;
// 依据下面的表格,咱们晓得 int* 是指向“整型”的指针,// 那么 pi 能够保留的是 int 类型的变量 i 的地址:pi = &i;
int** ppi;
// ppi 能够保留的是 int* 类型的变量 pi 的地址:ppi = π
// 祝贺你,当初你曾经晓得了怎么定义 int** 类型的变量和给它赋值
// 咱们先写到这里
return 0;
}
深刻思考
如果定义有 int** p
(为了不便,咱们暂且把 p
认为是 ppi
的别名),那么 p
, *p
, **p
, p + 1
, *p + 1
, *(p + 1)
, **p + 1
, *(*p + 1)
, **(p + 1)
别离是什么?
先看最指针本身
乍一看有点多,开始有点慌是吧,没关系,咱们先看不带加法运算的前三个:p
, *p
以及 **p
从下面的代码咱们曾经晓得 p
就是寄存 int*
类型变量的地址的变量
// 从下面暂停下来的中央咱们持续
// 咱们都晓得,在指针后面加个 * 就是“获得这个指针指向的地址里的值”// 因为 pi 寄存的是 i 的地址,那么 *pi 就是获得 i 寄存的值,类型是 int
// 同理,*ppi 获得的是 pi 寄存的值,类型是 int*
printf("*pi = %d, *ppi = %p\n", *pi,*ppi);
// 输入 *pi = 418, *ppi = 0000002D6FF2FD58(*pi = 前面的值在每台机器上都可能不一样)// 既然 *ppi 是 int*,那也就是说咱们还能够对它再做一次解援用,// 拿到 *ppi 这个地址里寄存的值,类型是 int
printf("**ppi = %d\n", **ppi);
// 输入 **pi = 418
这时,你曾经把握 p
,*p
以及 **p
别离是什么了
再看指针的加法运算
接下来咱们还是先挑最简略的,把不带 *
的拿进去:p + 1
,指针 p
做了个加法运算。
那么它加的这个 1
是什么?数字 1
?1
位?1
字节?
都不是,C 指针加法运算里的数字操作数的单位是 指针的长度
,也就是说 p + 1
示意的时候内存中,紧挨着 p
的下一个可用空间的地址:
printf("ppi = %p, ppi + 1 = %p\n", ppi, ppi + 1);
// 输入 ppi = 0000008CA96FFB78, ppi + 1 = 0000008CA96FFB80
// 并且咱们能够看到 0000008CA96FFB80 - 0000008CA96FFB78 = 8(16 进制)// 恰好等于 x64 零碎下 1 个指针的大小:8 字节
那 *(p + 1)
是什么你应该也晓得了,就是 p + 1
这个地址(假如是非法的)寄存的值,类型是 int*
。
而 *p + 1
就是 *p
这个地址再偏移了 1 个指针长度
printf("*ppi = %p, *ppi + 1 = %p\n", *ppi, *ppi + 1);
// 输入 *ppi = 0000002D6FF2FD58, *ppi + 1 = 0000002D6FF2FD60
printf("pi = %p\n", pi);
// 输入 pi = 0000002D6FF2FD58
// 能够看到 *ppi == p
好了,还剩下最初三个:**p + 1
, *(*p + 1)
, **(p + 1)
,先试试联合下面的常识,想一下在咱们的例子中这三个别离是什么,想好之后再看上面的答案测验一下本人了解得对不对:
**p + 1
:**p
获得的是int
,值是 418,所以**p + 1
是 419*(*p + 1)
:*p + 1
是0000002D6FF2FD60
,那么*(*p + 1)
就是获得这个地址中的值(假如地址都是非法的)**(p + 1)
:先对p + 1
这个地址做解援用,失去新的地址*(p + 1)
,而后再对新的地址做解援用,失去的是个int
(假如地址都是非法的)
再给你 int***
你也能答复了
当初再给你 int***
,置信你也晓得它是什么了:
C 语法 | 释义 |
---|---|
int*** |
指向 指向指向整型的指针的指针 的指针 |
… | 指向 … 的指针 |
拓展浏览
仔细的你应该发现了,后面屡次对指针做加法运算的时候都有注明 假如地址非法
,那么这个 假如非法的地址
到底是什么呢,能够浏览这篇《C 指针与数组》(撰写中,敬请期待)
书籍举荐
- 《驯服 C 指针》[日]前桥和弥 著 豆瓣 | 京东
本文首发于自己博客:https://yian.me/blog/what-is/pointer-to-pointer-in-c-programing-language.html