進一步理解指針:一維數組和二維數組轉換

先看下列代碼的輸出是什麼?

int main()
{
    int m[5] = { 0,1,2,3,4 };
    int* p = (int*)(&m+1);
    printf("%d,%d\n", *(m+1), *(p-1));
    return 0;
}


要知道這個輸出,最關鍵的是要理解指針操作的“加”和“減”,假設有一指針ptr,則“ptr”中的“1”是指ptr所指類型的大小。因此上述代碼中的“&m+1”中的“1”實質是“sizeof(m)”,而後一個“1”則“sizeof(m[0])”。

爲什麼“&m+1”中的“1”是“sizeof(m)”?根本原因在於“&a”實際是一個二維數組“int (*)[5]”的首地址,而不是一維數組“int [5]”的首地址,看下面這段代碼就容易理解:

int main()
{
    int m[5] = { 0,1,2,3,4 };
    int* p = (int*)(&m+1);
    printf("%d,%d\n", *(m+1), *(p-1));


    int (*pp)[5] = (&m+1);
    --pp;
    printf("%d\n", pp[0][4]);
    return 0;
}


而要注意:上面的“p”仍然是一個一維數組的首地址!下面演示把一個一維數組變成真正的二維數組使用:

int main()
{
    int m[5] = { 0,1,2,3,4 };

    int** ppm = (int**)m; // 這裏也可以寫成:int** ppm = (int**)&m;,&m、m和&m[0]的區別是什麼?
    int (*pm)[3] = (int (*)[3])ppm;
    printf("%d\n", pm[1][1]);

    return 0;
}


下列代碼的輸出又是什麼了?或者代碼有問題?

int main()
{
    int m[5] = { 0,1,2,3,4 };


    int** ppm = (int**)m;
    int (*pm1)[3] = (int (*)[3])&m;
    int (*pm2)[3] = (int (*)[3])ppm;
    int (*pm3)[3] = (int (*)[3])&ppm;
    printf("%d,%d,%d\n", pm1[1][1], pm2[1][1], pm3[1][1]);


    return 0;
}


指針加減,要看它指向的類型,移動大小是指向類型的大小。實際上,內存中的pm[0]和pm[1]是連續在一起的,並沒有分成兩行,只是爲了理解二維數組經常被畫成二維表格形式。
關聯貼:常見指針定義解讀http://blog.chinaunix.net/uid-20682147-id-4344901.html)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章