---
# System prepended metadata

title: 指標
tags: [語法]

---

---
title: 指標
tags: 語法
robots: noindex, nofollow
langs: zh
---
:::success
# 指標(Pointer)
指標概念有些抽象，但其實並不難
概念就是儲存一個變數，這個變數描述著另一個變數在記憶體中的位置
指標所佔的Byte數量是因執行平台而定的，C語言中有```size_t```這個型別來表示他所佔的Byte(```size_t```為無號整數)
一般來說在64位元平台上，Pointer所佔的大小都是8個Byte
32位元平台上則是4個Byte

## 語法
### 基礎操作
```cpp
#include <cstdio>
int main(){
    int a = 10, b;
    int *a_ptr, *b_ptr;
    a_ptr = &a;
    b_ptr = &b;
    printf("%d %d\n", *a_ptr, *b_ptr);
}
```
這個範例之中包含了幾個語法
1. 宣告
宣告時在變數名稱前面加上\*就是指標型態了
2. 賦值
直接用等於給他指標型態的變數就可以了
3. 取址
用&符號可以取得一份般變數的位置
4. 解址
把指標解開用\*符號放在前面就可以解開當一般變數使用了
可以拿來做正常加減運算與輸出
### 動態分配空間
指標最重要要實現的功能，便是在執行階段分配具有**跨函數生命週期**與動態大小的記憶體空間，語法上C與C\+\+有所不同，以下以C++做示範
#### \[動態分配陣列\]
```cpp
#include <cstdio>
#include <csting>
using namespace std;
int main(){
    size_t n;
    scanf("%lu", &n);
    // 在Heap中動態分配陣列
    int arr = new int[n];
    // 初始化動態分配的空間成0
    memset(arr, 0x00, sizeof(int)*n);
    //以下為示範寫入與讀出記憶體
    for(int i = 0 ; i < n ; ++i){
        scanf("%d", &arr[i]);
    }
    size_t q;
    while(scanf("%lu", &q) != EOF){
        // 檢查不合理的記憶體存取
        if(q < n)
            printf("%d", arr[q]);
        else
            printf("Array Access Out of Bound\n");
    }
    return 0;
}
```
#### \[動態分配物件\]
```cpp
#include <cstdio>
using namespace std;
struct stack{
    int arr[100];
    int top;
};
int main(){
    stack *stk = new stack();
    stack->top = 0;
    /*...*/
    delete stk;
    return 0;
}
```
要注意的是動態分配的記憶體空間一定要記得釋放掉(C\+\+的寫法為使用```delete```)，不然他會一直佔用記憶體直到整隻程式結束！
## 用途
一般來說指標用在int, double等一般型態的變數上不太好用，我們會更傾向使用「參考」(reference)。實戰中多會使用在struct與class的instance上，減少物件的複製次數；以及用在陣列上。

陣列本身其實就是一個指向陣列開頭的指標，\[\]運算子其實在做的就是移動+解開指標。(但在宣告時\[\]不作為運算子看待，而是修飾型別的修飾語，所以\[\]此時與\*的意義不同)
:::success