2014-09-02 68 views
1

以下程序顯示a和數組共享相同的地址。 我應該如何理解這種行爲? 是否爲& arr指針arr的地址,其中包含10個字符的開始地址?數組指針的地址,&array

#include <stdio.h> 

int main() 
{ 
    char arr[10] = {0}; 

    char* a = (char*)(&arr); 

    *a = 1; 

    printf("a=%p,arr=%p.\n", a, arr); 
    printf("%d\n", arr[0]); 
    return 0; 
} 
+0

'&arr'是'arr'的第一個元素的地址。當然,'a'具有相同的值,因爲您首先爲其分配了該值。 – 2014-09-02 14:59:37

+0

@亞歷克斯:你必須學習的第一件事就是沒有「指針'arr'」這樣的東西。 'arr'數組是數組,而不是指針。那裏沒有任何指針。有大量的信息正確地解釋了網絡上的數組。 – AnT 2014-09-02 15:32:37

回答

2

當您分配C中的數組,什麼你得到如下:

  +---+ 
    arr[0]: | | 
      +---+ 
    arr[1]: | | 
      +---+ 
      ... 
      +---+ 
arr[N-1]: | | 
      +---+ 

就是這樣。沒有爲名爲arr的對象留出單獨的內存位置來存儲數組第一個元素的地址。因此,陣列的第一個元素(&arr[0])的地址與數組本身的地址(&arr)是相同的

除了當它是sizeof或一元&運營商的操作數,或是一個字符串被用來在聲明初始化另一個數組,類型「的T N元件陣列」的表達將被轉換(「衰減」)轉換爲類型爲「指向T的指針」的表達式,並且表達式的值將是該數組的第一個元素的地址。

因此,在第一個printf調用中的表達式arr的類型是char [10];根據上述規則,表達式「decays」鍵入char *,值爲arr[0]的地址。

在表達式&arr中,arr是一元運算符&的操作數,所以不應用轉換;代替獲得char **類型的表達式,您會得到char (*)[10]類型的表達式(指向10個元素的數組char)。同樣,由於陣列的第一個元素的地址與整個陣列的地址相同,因此表達式arr&arr具有相同的

0

通過arra打印出的地址是該陣列arr的第一個元素的存儲器地址。 (請記住,數組的名稱總是指向該數組的第一個元素的指針)。這是因爲在定義了數組arr之後,您將a定義爲指向內存中相同地址的指針。

1

在習慣C中,你應該寫char *a = arr;char *a = &(arr[0]);&arr通常是char **。即使現代(C++)還是傳統編譯器自動,它是不正確的C.

作爲arrchar陣列,arr[0]char和ARR是一樣的&(arr[0])所以它是一個char *。如果你習慣於其他語言,這可能很奇怪,但它是如何工作的。如果arr是包括struct在內的任何其他類型的數組,它將是相同的。

+0

'&arr'將是'char(*)[10]',這是一個指向10個'char'數組的指針。 @FrédéricHamidi – alk 2014-09-02 16:21:52

+1

@FrédéricHamidi你可能會相信你想要的東西,但真正重要的是編譯器會相信什麼:-),我已經編輯了我的帖子,以便更清楚。 – 2014-09-02 17:11:08

0

按照C標準(6.3.2.1左值,數組和功能指示器)

3除了當它是sizeof操作或一元& 操作者的操作數,或是一個字符串文字用於初始化一個數組,一個 具有類型爲'''的數組的表達式被轉換爲 表達式,其類型爲指向類型''的指針,該指針指向數組對象的初始 元素,並且不是左值。如果數組對象 具有寄存器存儲類,則行爲未定義。

數組的地址是其第一個元素的地址。所以,雖然這些類型不同

char (*)[10](即對應於& ARR)和char *(也就是在鑄造用在聲明 的char * A =(字符*)(& ARR);),他們將具有相同的值那就是數組的第一個元素的地址。

如果你不會用鑄件然後通過表達初始化的指針的正確定義& ARR將

char (*a)[10] = &arr; 

的差異被認爲是把指針遞增。爲了定義指針a,表達式++a的值將比初​​始值大sizeof(char)。對於指針來說,表達式++的值比初始值大10 * sizeof(char)

在你的情況表達*a的類型是char,你可以寫*a = 1;,而在我的情況下表達*a的類型將是char[10],你可以不寫*a = 1;