# 指针的定义 指针是一个变量,存在栈上。它的作用是用来存放另一个变量的地址。 什么意思呢? 比如我们前面说的执行回调函数的时候,必须传入函数的地址。那么在回调函数的形参上就必须写一个能表达函数地址的变量,也就是函数指针。 具体可以参考 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 放到后面一节讲,是因为为了和指针数组进行对比。