關於數組與指針的區別

最近在動手寫一個RMI類似的庫,剛剛開始,在實現一個類的時候,注意到了以前被忽略的問題。

指針和數組,絕對不是一回事。

程序的原型是這樣的:

bool copy(uint8_t** data , uint32_t len);
後來我使用的時候,定義了一個uint8_t的數組,想通過&<數組名>的方式傳遞一個指針的指針,可恥的失敗了。

調試一番後,果斷髮現傳進去的值,居然不是我想的指針的指針,而是數組的首地址。然後把數組換成了指針,獲得了期望的結果。

測試程序如下:

#include <stdio.h>
#include <stdint.h>

int main( int argc , char** argv)
{
	int   data[4] = {0};
	char* str = "mm test";
	printf("data is %d\n" , data);
	printf("data addr is %d\n" , &data);
	printf("str is %d\n" , str);
	printf("str addr is %d\n" , &str);
	return 0;
}

     結果是:

     

     從程序打印的結果就可以看出指針和數組完全是兩個不同的東東。

     爲什麼會有這樣的差異,在google了一番之後,找到了滿意的答案。

     http://www.cnblogs.com/csyisong/archive/2010/03/18/1688877.html

     以下內容爲轉載:

    1 指針和數組的區別
    指針和數組的分配
    數組是開闢一塊連續的內存空間,數組本身的標識符(也就是通常所說的數組名)代表整個數組,可以使用sizeof來獲得數組所佔據內存空間的大小(注意, 不是數組元素的個數,而是數組佔據內存空間的大小,這是以字節爲單位的)
    2 空間的分配
    這裏又分爲兩種情況:

    第一,如果是全局的和靜態的
    char *p = “hello”;
    這是定義了一個指針,指向rodata section裏面的“hello”,可以被編譯器放到字符串池。在彙編裏面的關鍵字爲.ltorg。意思就是在字符串池裏的字符串是可以共享的,這也是 編譯器優化的一個措施。
    char a[] = “hello”;
    這是定義了一個數組,分配在可寫數據塊,不會被放到字符串池。

    第二,如果是局部的
    char *p = “hello”;
    這是定義了一個指針,指向rodata section裏面的“hello”,可以被編譯器放到字符串池。在彙編裏面的關鍵字爲.ltorg。意思就是在字符串池裏的字符串是可以共享的,這也是 編譯器優化的一個措施。另外,在函數中可以返回它的地址,也就是說,指針是局部變量,但是它指向的內容是全局的。
    char a[] = “hello”;
    這是定義了一個數組,分配在堆棧上,初始化由編譯器進行。(短的時候直接用指令填充,長的時候就從全局字符串表拷貝),不會被放到字符串池(同樣如前,可 能會從字符串池中拷貝過來)。注意不應該返回它的地址

    繼續在網上看,後面看到了一個程序,可以更深刻地認識到數組和指針的區別。
    以下程序的打印值是什麼?
          int c[5] = {1,2,3,4,5};

          int *ptr = (int *)(&c +1);

          printf("%d %d\n", *(c +1), *(ptr-1));
   如果答案是2,1,那就錯了 , 答案是2,5。爲什麼?關鍵就是(&c+1)。
  上面已經說到,數組本身的標識符代表整個數組。並且數組和指針的分配根本不是一樣的。可以這麼理解,數組定義的時候,數組名代表一整塊區域,因爲沒有任何指針指向數組所在的內存區域,所以&<數組名>只能返回數組的首地址。而在定義指針的時候,指針本身是佔據一塊4字節的內存的,這塊內存的地址,就是指針的指針。
   (&c+1)實際得到的是(&c+sizeof(c))。看到這裏是不是想起了什麼?假設我們有個int*的指針ptr , ptr+1不就是指向下一個int的指針嗎?原來對於數組我們應該把它當做類型,這纔是正確的。是的,它和指針不是一回事,它其實應該是像int char short這樣的類型。

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