1. 程式人生 > >C語言事實上不簡單:數組與指針

C語言事實上不簡單:數組與指針

本質 而不是 getchar() alt 由於 == sizeof 不同 來看

之前在寫C的時候,沒怎麽留意數組。就這麽定義一個。然後顛來倒去的使用即可了。只是後來碰到了點問題。解決後決定寫這麽一篇博客,數組離不開指針。索性就放一起好了。

如今我定義了一個數組:int cc[10];

環繞這個數組有好幾種指針:cc, cc+1, &cc[0], &cc, &cc+1等等。你知道它們都是什麽含義嗎?試試執行下面帶代碼:

#include <stdio.h>

int main()
{
    int cc[10];

    printf("%x\n", cc);
    printf("%x\n", cc+1);
    printf("%x\n", &cc[0]);
    printf("%x\n", &cc);
    printf("%x\n", &cc+1);

    getchar();
    return 0;
}
cc,這是學數組時第一個接觸的"指針",最為熟悉,它是數組的首個元素。

cc+1,這是指向數字第二個位置的指針。

&cc[0],這個事實上就是cc,指向數組的首個元素。

&cc。這是什麽玩意兒?指向指針的指針?

&cc+1,假設上面的意思是指向指針的指針。那這個豈不是指向野地址了?

如果執行環境是32位機。而且數組首地址為0x28ff00。那麽:

cc的結果為0x28ff00,這點毫無疑問。

cc+1的地址是0x28ff04而不是0x28ff01,由於一個int占用了4個字節的空間。cc+1事實上是當成cc+1*sizeof(int)來看待。

&cc[0]的結果是0x28ff00,cc[0]表示的是數組的首個元素。那麽&cc[0]自然就是首個元素的地址了。&cc[0] == cc。

&cc,這個就難說了。指針cc的值是0x28ff00,&cc表示這個指針本身的地址,我們怎麽可能會知道這個地址?輸出是個隨機地址嗎?隨機數的話這個輸出全然沒有意義啊。假設不是隨機地址的話,難不成還是0x28ff00?這種話a不就等於&a了?明顯不正確吧。

對於基本類型的指針,如int *tt; 那麽*tt是其值,&tt是指針的地址,&tt != tt

可是上述的cc是個數組。實際上。&cc被編譯成了&cc[0],可是其含義不同,&cc指向的是整個數組的開頭。

&cc與cc的指向能夠用下圖來形象表示:

技術分享

上圖能夠看出,&cc事實上代表的是int(*)[10],那麽&cc+1就能夠理解為cc + sizeof(cc)/4,之所以除以4是由於int型指針++事實上是移動了4個字節。

又或者說%cc == cc + sizeof(cc)/4 == cc + 10。所以&cc+1的值為0x28ff28。

可見我們尋常使用的數組名,並不能單純的當成指針看待。數組名的本質是代表數組對象的變量名,是一個左值,是一個不能被改變的左值。

可是因為在程序中不保存數組的大小,所以通過數組名僅僅能訪問數組的左值。不能訪問數組的右值。

因為這個原因,數組名在作為右值使用的時候被賦予另外一個新的意義——指向數組第一個元素的指針。這就是array-to-pointer轉換規則。

依據標準規定。僅僅有當數組名作為sizeof、&運算符的操作數的時候。它是一個左值,其類型為數組類型。除此之外的全部情況,數組名都是一個右值,被編譯器自己主動轉換為指針類型,這樣的情況下我們就說數組名是一個指針。而且是一個指針常量。



接下來是另外一些有趣的東西,我們結合sizeof與數組輸出各類值。

下面程序的輸出結果是什麽?建議思考後再執行程序來驗證答案。

#include <stdio.h>

int main()
{
    int cc[10];
    printf("%d\n", sizeof(cc[0]));
    printf("%d\n", sizeof(cc));
    printf("%d\n", sizeof(&cc));
    printf("%d\n", sizeof(int(*)[10]));

    getchar();
    return 0;
}
sizeof(cc[0]),一個int的大小。輸出4,沒問題。

sizeof(cc),註意不要和上面搞混。這不是數組首地址的指針,cc在這裏是左值。其為數組類型。所以結果為40。

sizeof(&cc),這個的答案應該是多少呢?註意了。cc在這裏還是左值,其為數組類型,但&cc不同於cc,無論數組怎麽復雜它始終是個指針,32位機上指針大小始終是4個字節。所以結果為4。

sizeof(int(*)[10]),這個事實上和上面的&cc是一個樣的,代表了整個數組,但還是指針,所以結果相同為4。

練習:以下的程序輸出結果是什麽(如果32位機):

#include <stdio.h>

int main()
{
    int *p[2];
    printf("%d\n", *p);
    printf("%d\n", sizeof(p));
    printf("%d\n", sizeof(&p));

    getchar();
    return 0;
}

答案是:隨機數、8、4

再來一個練習:下列程序的輸出是什麽?

#include <stdio.h>

int main()
{
    char str[]="hactrox";
    char *p = str;
    printf("%d %d\n", sizeof(str), sizeof(p));

    getchar();
    return 0;
}

答案:8、4(不要忘了‘\0‘)


C語言事實上不簡單:數組與指針