【C語言入門】172.指標陣列

在這篇文章,我們來介紹指標陣列。

指標陣列是甚麼呢?

我們之前介紹過陣列,陣列的初始化是這樣的

int v[3] = {1, 2, 3};

指標陣列初始化

int v[3] = {1, 2, 3};

int *p[3] = {&v[0], &v[1], &v[2]};

指標存的必定是某個變數或是某個已經配置好的空間的位址。

指標陣列的本質還是陣列。

#include <stdio.h>
#include <string.h>

int main()
{
    int v[3] = {1, 2, 3};

    int *p[3] = {&v[0], &v[1], &v[2]};
    
    int i;
    for(i = 0; i < 3; i++){
        *p[i] = 0;
    }

    return 0;
}

在以上的範例中,p[i] 其實就是 v[i] 的位址。

因此我們可以把 p[i] 一一拿出來,然後再一一對存的位址取得變數。

#include <stdio.h>
#include <string.h>

int main()
{
    int v[3] = {1, 2, 3};

    int *p[3] = {&v[0], &v[1], &v[2]};
    
    int i;
    for(i = 0; i < 3; i++){
        *p[i] = 0;
    }

    //隨機存取
    *p[2] = 5;
    
    return 0;
}

如果我們把 p 陣列一一存 v 這個整數陣列的元素的話,我們就可以讓 p 陣列用起來跟 v 陣列非常類似,之是前面多了一個星號(*)。

我們再來看看之前提過的例子。

#include <stdio.h>
#include <string.h>

int main()
{
    int v[3] = {1, 2, 3};

    int *n = v;
    
    int i;
    for(i = 0; i < 3; i++){
        n[i] = 0;
    }

    n[2] = 5;
    
    return 0;
}

用 n 的話,我們只存陣列的開頭位置。

用 p 的話,我們存的是多個的位址。存多個位址代表我們可以做得更複雜,例如我們可以讓存的位址是顛倒的。

#include <stdio.h>
#include <string.h>

int main()
{
    int v[3] = {1, 2, 3};
    int *p[3] = {&v[2], &v[1], &v[0]};
    
    int i;
    for(i = 0; i < 3; i++){
        *p[i] = 0;
    }

    //隨機存取
    *p[2] = 5;
    
    return 0;
}

這時候 v[0] 會被設為 5。

#include <stdio.h>
#include <string.h>

int main()
{
    int a = 1, b = 2, c = 3;

    int *p[3] = {&a, &b, &c};
    
    int i;
    for(i = 0; i < 3; i++){
        *p[i] = 0;
    }

    //隨機存取
    *p[2] = 5;
    
    return 0;
}

*p[2] 代表的是 c 這個變數。

我們也可以存陣列的開頭位址。

#include <stdio.h>
#include <string.h>

int main()
{
    int a[2] = {1, 2};
    int b[2] = {3, 4};
    int c[2] = {5, 6};

    int *p[3] = {a, b, c};
    
    int i;
    for(i = 0; i < 3; i++){
        for(j = 0; j < 2; j++){
            p[i][j] = 0;
        }
    }
    //隨機存取
    p[2][0] = 7;  // (&c[0])[0] = 7

    return 0;
}

p[0] 存的是 a,a 本身是個陣列,沒辦法直接存成 p[0],因為 p[0] 要的是一個整數的指標。

因此 a 這個整數陣列會隱性轉型成一個整數指標,也就是 a[0] 的位址。

p 的每個元素是陣列,當我們循序存取的過程中,會把 a[0]、a[1]、b[0]、b[1]、c[0]、c[1] 一一設成 0。

當我們要隨機存取 p[2][0] = 7。

p[2] 是 c[0] 的位址,從 c[0] 的位址走 0 格。

& c[0] 加 0 再取變數,也就是 c[0] 這個變數。

以上的寫法,並沒有要求 a、b、c 都一樣大,因為我們是通過指標存取。

p 也不需要知道 a、b、c 有多大,他只會獲得 3 個開頭位址。

#include <stdio.h>
#include <string.h>

int main()
{
    int a[2] = {1, 2, 7, 8};
    int b[2] = {3, 4};
    int c[2] = {5, 6};

    int *p[3] = {a, b, c};
    
    int i;
    for(i = 0; i < 3; i++){
        for(j = 0; j < 2; j++){
            p[i][j] = 0;
        }
    }
    //隨機存取
    p[0][2] = 9;
    p[1][2] = 10; //未定義行為
    return 0;
}

我們來看這行程式。

 p[0][2] = 9;

p[0][2] 相當於從 a[0] 走2格,也就是把 7 改成 9。

 p[1][2] = 10; //未定義行為

p[1][2] 相當於從 b[0] 的位置走2格,可是 b[0] 之後只有 1 格,因此 p[1][2] = 10; 是未定義行為。

如果 p[i] 是 p[0] 的話,他就有 4 個可以用。

如果 p[i] 是 p[1] 的話,他就只有 2 個可以用。

Leave a Comment

Your email address will not be published. Required fields are marked *