# 指针的定义
指针是一个变量,存在栈上。它的作用是用来存放另一个变量的地址。
什么意思呢?
比如我们前面说的执行回调函数的时候,必须传入函数的地址。那么在回调函数的形参上就必须写一个能表达函数地址的变量,也就是函数指针。
具体可以参考 https://mengkang.net/1007.html
> 每一个数据类型都会对应一个数据类型的指针,虽然都是地址,但是为了编译器方便,需要我们在使用时说明该指针的类型。当然有时候也可以使用泛指针,因为有时候无法确定指针的类型,有时候需要做指针类型的转换。
```c
type *name
```
type | 指针的类型
------- | -------
name | 变量名
比如
```c
int *a;
char *b;
```
> 原来我有一个误区,总以为`*name`是指针变量,`name`才是指针变量,`*`只是告诉编译器,后面的变量是指针类型。也可以加空格`int * a`
# 指针的使用
```c
#include <stdio.h>
int main ()
{
int var = 100;
int *p;
p = &var; // & 取地址
printf("var 的地址: %p\n", &var );
printf("p 的值: %p\n", p );
printf("*p: %d\n", *p ); // * 加指针,表示取指针对应的地址的值
printf("*(&var): %d\n", *(&var)); // 首选取var的地址,然后再通过*来取出该地址的值
return 0;
}
```
结果示例
```c
var 的地址: 0x7fff5447da88
p 的值: 0x7fff5447da88
*p: 100
*(&var): 100
```
# 指针的偏移
下面的代码能通过编译吗?
```c
double a = 10.1;
int *p = &a;
```
无法通过编译,因为指针的类型,标识了存储的数据类型所以占用的内存大小,方便指针的偏移,比如下面的数组循环案例:
```c
#include <stdio.h>
int main ()
{
int var[3] = {10, 100, 200};
int i, *ptr;
ptr = var;
for (i = 0; i < 3; i++)
{
printf("存储值:var[%d] = %d\n", i, *ptr);
ptr++; //移动到下一个位置
}
return 0;
}
```
打印结果
```
存储值:var[0] = 10
存储值:var[1] = 100
存储值:var[2] = 200
```
>指针不管是`++`,还是`--`偏移的量都是该指针数据类型的单元大小。
所以`ptr++`能依次输出数组的值。
# 二级指针
也就是指向指针的指针,再通俗点就是,a 是指针变量,a里面存了b的地址,而b也是一个指针。
```c
#include <stdio.h>
int main(int argc, char const *argv[]) {
int i = 10;
int *p = &i; // p 里面存了i的地址
int **p2 = &p; // p2 里面又存了p的地址
printf("%d\n", **p2);// 根据前面的规则 * 就是取该地址的值,这里最后输出10
return 0;
}
```
二级指针的使用 https://mengkang.net/719.html
# 数组指针
参考 https://mengkang.net/1010.html#blog-title-2
放到后面一节讲,是因为为了和指针数组进行对比。