程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> C語言其實不簡單:數組與指針

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

編輯:關於C

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

現在我定義了一個數組:int cc[10];

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

#include 

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 

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 

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 

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

    getchar();
    return 0;
}

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


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved