---
# System prepended metadata

title: 關於指針的一些事情
tags: [挖坑, C++]

---

---
title: 關於指針的一些事情
tags: C++,挖坑
---
# 快速回顧
```cpp=
int * a_pointer;
int a_value = 10;
// & 取址符號 address-of operator 
a_pointer = & a_value;
// * 解址(參)符號 dereference operator
int another_value = * a_poointer;
// 跟宣告指針的 * 不一樣喔
```
# Pointers and Arrays
指針變數可以存放陣列的起始位置
但是陣列變數不可以任意更改成其他指針
```cpp=
int * pointer;
int array[10];
//可以
pointer = array;
//會報錯
array = a_pointer
```
:::danger
運算式必須是可修改的左值
:::
>我猜 array這個名字底下應該是宣告成 const
>有關 const 請見這篇 "挖坑"

### 位移取值符號`[]`
其實不只陣列可以用這個方法取值
指標也可以
```cpp=
int * pointer = new int();
// 下面是做相同的事情
*(pointer+1)=10;
// +1會根據指標的型態 移動對應的大小
// 像是 int 就是 4個byte (沒記錯的話
pointer[1] = 10;
```
當然 陣列也可以使用第 3 行的方法
:::danger
注意 上面其實是一個非常危險的行為
因為我只有給指標一個位置
但是我卻隨便更改了他下一個位置的值
**但你並不知道這個位置是不是有給誰使用**
**所以使用這種位置取值時一定要確認好範圍**
:::
### 常數指針
可以讀取值 但是不能更改值
跟函數常數參照很像 [參考這篇](https://hackmd.io/hYyfy28VROWMBN2ZfmYZCQ)
```cpp=
int x;
      int *       p1 = &x;  // 非常數指針指向非常數變數
const int *       p2 = &x;  // 非常數指針指向常數變數
      int * const p3 = &x;  // 常數指針指向非常數變數
const int * const p4 = &x;  // 常數指針指向常數變數
```
### 空指針
顧名思義 指向 空 的指針
作用為一個很有彈性的容器
你可以把任何型態的位置存進去
直到確定型態後再將他轉型
```cpp=
// increaser
#include <iostream>
using namespace std;

void increase (void* data, int psize)
{
  if ( psize == sizeof(char) )
  { char* pchar; pchar=(char*)data; ++(*pchar); }
  else if (psize == sizeof(int) )
  { int* pint; pint=(int*)data; ++(*pint); }
}

int main ()
{
  char a = 'x';
  int b = 1602;
  increase (&a,sizeof(a));
  increase (&b,sizeof(b));
  cout << a << ", " << b << '\n';
  return 0;
}
```
:::info
上面就是用空指針接受變數的位置
其實也不用多宣告兩個指針去接轉型後的空指針
畢竟指針就是位置(:tea:
:::
### null指針
是一個指向 ==沒有地方== 的指針
有三種方式可以宣告
```cpp=
int * p = 0;
int * q = nullptr;	
int * r = NULL;
```
其中`NULL`代表的是`0`或`nullptr`
在某些標頭檔會宣告起來
### 函數指針
就是指向函數的指針
長相有點不一樣 但邏輯還是在的
```cpp=
return_type (*function_name)(type_1,type_2...) = a_function;
```
官方例子
```cpp=
// pointer to functions
#include <iostream>
using namespace std;

int addition (int a, int b)
{ return (a+b); }

int subtraction (int a, int b)
{ return (a-b); }

int operation (int x, int y, int (*functocall)(int,int))
{
  int g;
// 這裡取值時的寫法要注意
  g = (*functocall)(x,y);
  return (g);
}

int main ()
{
  int m,n;
  int (*minus)(int,int) = subtraction;

  m = operation (7, 5, addition);
  n = operation (20, m, minus);
  cout <<n;
  return 0;
}
```
