# 指針的定義
指針是一個變量,存在棧上。它的作用是用來存放另一個變量的地址。
什么意思呢?
比如我們前面說的執行回調函數的時候,必須傳入函數的地址。那么在回調函數的形參上就必須寫一個能表達函數地址的變量,也就是函數指針。
具體可以參考 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
放到后面一節講,是因為為了和指針數組進行對比。