1. 程式人生 > >C語言之指向一維陣列的指標

C語言之指向一維陣列的指標

int array[5] = {1, 2, 3, 4, 5}; // 定義陣列
int *intptr = array; // 定義指向陣列元素的指標
int (*arrayptr)[5] = &array; // 定義指向陣列的指標

上述三條語句分別定義了陣列, 指向陣列元素的指標和指向陣列的指標. 記憶體情況如圖示:
記憶體

對於指向陣列元素的指標很好理解, 但是怎樣理解 指向陣列的指標呢?

  • 怎樣理解指標?
    指標可以認為是一個變數, 該變數標記了一段記憶體, 這段記憶體的特點是其中儲存了固定型別的資料.
    比如上面的ptr初始時標記了array[0]所在的一段記憶體單元, 這段記憶體單元儲存的是int型別的資料(因為ptr是int型別的指標). 也可以令 ptr = &array[3]
    , 這樣ptr標記的就是array[3]所佔的記憶體單元, 但是其中儲存的仍然必須是int型別.
    考慮結構體的情況:
struct student {
    char name[10];
    int age;
};
student Jane = {"Jane', 18};
student *studentptr = Jane;

studetptr初始時標記的是Jane所佔的記憶體空間, 該記憶體空間儲存的資料必須是struct student型別的.
從上面可以看出, 只要有一段記憶體, 並且這段記憶體儲存的內容具有固定的型別我們就可以定義一個指向它的指標.

  • 陣列是一種型別嗎?


    所謂型別, 不過是對記憶體中資料的解釋的約定, 我們將Jane所佔的前10個位元組中的內容解釋為字元, 後4個位元組解釋為整數, 然後我們就約定約定這14個位元組的型別是struct student. 陣列 不是一種固定的型別, 但是我們可以將 具有5個int元素的陣列 認為是一種型別, 這種型別在記憶體上的特點是連續儲存5個整形資料. 我們自然可以位0x1000到0x1004這段記憶體定義一個指標.

  • 如何解釋語句 int (*arrayptr)[5] = &array?
    *arrayptr 表示arrayptr是一個指標;[5] 表示指標指向的物件的型別是具有五個元素的陣列;int 表示該陣列的元素是int型別的. array

    是一個int [5] 型別的陣列, 取它的地址初始化arrayptr. 值得注意的是此時陣列名array不再表示陣列首元素的地址.

  • 如何通過指向陣列的指標訪問陣列的元素?

    • (*arrayptr)[0] == array[0] 首先arrayptr是指向 int [5] 型陣列的指標, 那麼解引 *arrayptr 得到一個 int [5] 型陣列, 然後自然可以通過下標訪問陣列的元素了.
    • arrayptr[0][0] == array[0] 想弄清楚這個表示式要明白以下幾個問題:
      (1) 二維陣列實際上就是元素為一維陣列的陣列
      (2) 二維陣列名可以看做指向其第一個元素(一維陣列)的指標
      (3) 在記憶體中2 x 5的二維陣列的儲存方式是下圖所示:
      二維陣列
      (4) 一維陣列array可以看做一個1 x 5的二維陣列
      現在我們將array看作一個只有一個元素的二維陣列, 並且該二維陣列的元素是 int [5] 型別的, 顯然arrayptr指向了該二維陣列的第一個元素(相當於二維陣列名) 所以我們可以通過下標運算子 arrayptr[0] 獲得二維陣列的第一個元素(實際上就是array陣列), 然後再次利用下標運算子 arrayptr[0][0] 獲取array陣列的第一個元素. 注意到無法使用 arrayptr[1]是錯誤的, 因為該二維陣列只有一個元素.
      下面的程式展示了指向一維陣列的指標:
// 指向一維陣列的指標
#include <stdio.h>

int main()
{
    int array[] = {1, 2, 3, 4, 5};
    int *ptr = array;
    int (*arrayptr)[5] = &array;

    // ptr與arrayptr都是指標型別
    printf("ptr所佔位元組數: %zu\tarrayptr所佔位元組數: %zu\n", sizeof(ptr), sizeof(arrayptr));

    // *ptrint型別 *arrayptrint [5]型別
    printf("*ptr所佔位元組數: %zu\t*arrayptr所佔位元組數: %zu\n", sizeof(*ptr), sizeof(*arrayptr));

    // 使用指向一維陣列的指標訪問陣列元素
    int sum = 0;
    int product = 1;
    for(int i = 0; i < 5; i++) {
        sum += (*arrayptr)[i];
        product *= arrayptr[0][i];
    }
    printf("一維陣列array元素的和是: %d\t乘積是: %d\n", sum, product);

    int matrix[3][5] = {
        {1, 2, 3, 4, 5},
        {6, 7, 8, 9, 10},
        {11, 12, 13, 14, 15}
    };

    // 指向一維陣列的指標指向二維陣列的元素
    arrayptr = matrix;      // 相當於arrayptr = &matrix[0]
    arrayptr[0][0]++;       // 相當於matrix[0][0]++
    printf("matrix[0][0]: %d\n", matrix[0][0]);

    (*(arrayptr + 1))[0]++; // 相當於matrix[1][0]++
    printf("matrix[1][0]: %d\n", matrix[1][0]);

    arrayptr[2][0]++;       // 相當於matrix[2][0]++
    printf("matrix[2][0]: %d\n", matrix[2][0]);

    return 0;
}