2012-08-09 60 views
3

我在我的書(和互聯網上的許多源)閱讀:的C指針:數組變量

數組變量到陣列中的第一個元素。

如果這是真的,那麼數組變量和第一個元素是不同。對?

這意味着通過下面的代碼,它會產生兩種不同的結果:

int main(){ 
    char msg[] = "stack over flow"; 
    printf("the store string is store at :%p\n",&msg); 
    printf("First element: %p\n",&msg[0]); 
} 

但我收到這兩種情況相同的結果。所以,通過這個例子,我想我們應該說:數組變量的第一個元素。 (因爲它有相同的地址)

我不知道這是真的還是錯的。請教我。

回答

8

數組變量表示數組佔據的整個內存塊,而不僅僅是數組的第一個元素。所以array不是array[0](參見sizeof array/sizeof array[0])相同。但數組的第一個元素與數組本身位於相同的內存地址。

說數組指向第一個元素也是不正確的,在大多數情況下,數組表達式衰減爲指向其第一個元素的指針,但它們是不同的東西(例如,參見sizeof)。

+0

你能告訴我更多關於這一點的信息:它位於相同的內存地址,但它不同。我不明白這一點,因爲我認爲,如果它找到了相同的地址,它應該是相同的。謝謝:) – hqt 2012-08-09 14:02:05

+0

@hqt地址**是**相同的,但重點是'msg'和'msg [0]'會有不同的表現。他們是兩種不同的類型。查看關於指針算術的註釋,例如'(&msg + 1)'並自己嘗試。 – pb2q 2012-08-09 14:05:54

+2

@hqt尺寸不同。數組msg佔用16個字節,其第一個元素只佔用這些字節中的第一個。這就像結構的第一個成員的地址與結構的地址一樣,但它們是不同的東西。如果你有一個x字節的實體A位於某個地址,而一個實體B的y字節位於相同的地址,那麼如果'x!= y',A和B是不同的實體。 (即使'x == y',它們也可以是不同的實體。) – 2012-08-09 14:06:06

5

它們指向相同的地址,即printf將顯示相同的值,但它們具有不同的類型。

  • 類型的&msgchar(*)[16],指針炭
  • 類型的&msg[0]char *,的陣列16字符指針

來測試此一種廉價的方式被做一些指針運算。嘗試打印&msg + 1

這個C FAQ可能證明是有用的。

+0

@dear downvoter有何評論? :-) – cnicutar 2012-08-09 14:10:49

+0

就我所見,您帖子中的所有內容都是正確的。+1來補償:) – Lundin 2012-08-09 14:37:30

5

數組變量整個數組。它將衰減成指向數組的第一個元素的指針。

如果你看一下類型:

  • msg類型爲char [16]
  • &msg的類型是char (*)[16]
  • &msg[0]的類型是char *

因此,在一個方面,其中msg的可以衰減爲數組,例如當作爲參數傳遞時,它的值將等於&msg[0]

讓我得出這樣的:

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+ 
|s|t|a|c|k| |o|v|e|r| |f|l|o|w|\0| 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+ 

想象一下數組,其中's'地處地址0x12345678的起點。

  • msg本身,指的是整個16字節的內存。就像當你說int a;時,a是指4個字節的內存。
  • msg[0]是該16字節的第一個字節。
  • &msg是其中陣列開始地址:0x12345678
  • &msg[0]是數組的第一元素的地址:0x12345678

這就是爲什麼&msg&msg[0]的值是相同的,但它們的類型不同。

現在的事情是,msg本身並不是頭等公民。你不能例如分配數組。這就是爲什麼在大多數情況下,陣列將衰減納入其指針。

如果你知道函數指針,這是非常相似的:

int array[10]; 
int function(int); 
  • int *var = arrayarray衰減到指針(&array
  • void *var = functionfunction衰減到指針(&function

請注意,在函數指針的情況下,我們喜歡ke EP的類型,所以我們寫:

int (*var)(int) = function; 

同樣,你可以用數組做:

int (*var)[10] = array; 
2
char myChar = 'A' 
char msg[] = 'ABCDEFGH' 

當你鍵入myChar你得到的價值。 但隨着味精你指向第一個字符(爲值,您必須使用味精[X])

msg = &msg[0] 

這可以幫助你理解,我想。

1

看看這樣說:

&msg = 0x0012 
&msg[0] = 0x0012 
&msg[1] = 0x0013 

在這種情況下&msg[1]指向msg+1。當您參考&msg&msg[0]時,您指的是相同的內存地址,因爲這是指針啓動的​​地方。由於char變量的大小隻有1個字節,所以增加數組變量會使指針增加+1。

如果你用一個整數來做同樣的技巧,你將增加指針+4個字節,因爲一個整數的大小是4個字節。

1

當您使用數組表達式時,編譯器將其轉換爲指向第一個元素的指針。這是在6.3.2.1中由1999 C標準指定的一種明確的轉換。3.這對您來說是一種方便,因此您不必編寫&array[0]來獲取指向第一個元素的指針。

轉換髮生在所有表達式中,除非數組表達式是sizeof的操作數或一元&或者是用於初始化數組的字符串文字。

您可以看到一個數組及其第一個元素通過打印sizeof arraysizeof array[0]而不同。

1

在大多數情況下,一個表達陣列型(「的T N元件陣列‘)的將與/轉換爲/‘衰變’到指針類型的表達式(’指針T」)代替,並且表達式的將是數組中第一個元素的地址。

因此,假設申報

int a[10]; 

的表達式的類型a是 「的int 10元件陣列」,或int [10]。但是,在大多數情況下,表達式的類型將轉換爲「指向int」或int *,表達式的值將等於&a[0]

此規則的例外是數組表達式是sizeof或一元&運算符的操作數,或者是用於在聲明中初始化另一個數組的字符串文字。

因此,基於我們的聲明之上,以下所有條件都爲真:

 
    Expression Type   Decays to  Value 
    ---------- ----   ---------  ----- 
      a int [10]  int *   address of the first element of a 
      &a int (*)[10] n/a   address of the array, which is the 
              same as the address of the first 
              element 
     &a[0] int *  n/a   address of the first element of a 
      *a int   n/a   value of a[0] 
    sizeof a size_t  n/a   number of bytes in the array 
              (10 * sizeof (int)) 
    sizeof &a size_t  n/a   number of bytes in a pointer to 
              an array of int 
    sizeof *a size_t  n/a   number of bytes in an int 
sizeof &a[0] size_t  n/a   number of bytes in a pointer to int 

注意表達a&a&a[0]都具有相同的(的第一個元素的地址a),但類型不同。類型很重要。假定:

int a[10]; 
int *p = a; 
int (*pa)[10] = &a; 

兩個ppa點的a的第一要素,我們將假定是在地址0x8000。執行線

p++; 
pa++; 

然而,p指向下一整數0x8004,假定4字節int S)後,邊pa指向整數的下一10元件陣列;也就是a0x8028)的最後一個元素之後的第一個整數。