2016-07-05 74 views
-1
#include<bits/stdc++.h> 
using namespace std; 
int main() 
{ 
    int a[101][101]; 
    a[2][0]=10; 
    cout<<a+2<<endl; 
    cout<<*(a+2)<<endl; 
    cout<<*(*(a+2)); 
    return 0; 
} 

爲什麼a + 2和*(a + 2)的值相同?提前致謝!2維數組如何存儲在內存中?

+2

可能只是巧合,如果你相信那樣的事情...... –

+0

即使打印的指針值相同,類型也不一樣。 – Jarod42

+1

你很幸運!今天,只有今天,在stackoverflow.com我們有一個特別的去:回答你自己的問題!創建一個小數組,例如'int a [2] [2]'。將四個值放入它中,比如說1,2,3和4.獲取一個指向第一個元素的指針,「int * p =&a [0] [0];'。然後用調試器查看'p'指向什麼,並回答你自己的問題。這真是個便宜貨!! –

回答

4

a是一個二維數組,這意味着一個數組的數組。但它衰退當在適當的上下文中使用一個指向數組的指針。所以:

  • a+2a衰減到指針時被傳遞到一個ostream,則得到此數組的第一元素的地址爲int大小101的陣列,即&(a[2][0])
  • *(a+2)的定義a[2]:它是一個大小爲101的數組,起始於a[2][0]。它衰變到一個指針爲int,而當你把它傳遞給你的第一個元素的地址一個ostream,這仍然是&(a[2][0])
  • **(a+2)定義a[2][0]。當你把它傳遞給一個ostream你得到它的int值,這裏10

但要注意:a + 2a[2]都指向同一個地址(static_cast<void *>(a+2)相同static_cast<void *>(a[2])),但它們指向不同類型:首先指向大小爲101的int數組,後者爲int。

+0

謝謝!這非常有幫助。 – Shubham

1

A 2維數組是數組的數組,所以它的存儲像這樣在存儲器中:

char v[2][3] = {{1,3,5},{5,10,2}}; 

Content: | 1 | 3 | 5 | 5 | 10 | 2 
Address: v v+1 v+2 v+3 v+4 v+5 

要訪問v [X] [Y],編譯器重寫它爲:*(v + y * M + x)(其中,M在第二尺寸指定)

例如,訪問v [1] [1],編譯器重寫它作爲*(v + 1*3 + 1) =>*(v + 4)

注意,這是不相同作爲指針(char **)的指針。 指向指針的指針不是數組:它包含並尋址到包含另一個地址的存儲單元。

訪問使用指針的指針2維陣列的構件,這是已完成:

char **p; 
/* Initialize it */ 
char c = p[3][5]; 
  1. 轉到由p內容所指定的地址;
  2. 將偏移量添加到該地址(在我們的例子中爲3);
  3. 轉到該地址並獲取其內容(我們的新地址)。
  4. 將第二個偏移量添加到該新地址(在我們的例子中爲5)。
  5. 獲取該地址的內容。

雖然經由傳統的2維數組的訪問部件,這些步驟如下:

char p[10][10]; 
char c = p[3][5]; 
  1. 獲取的p地址和綜所述第一偏移量(3)中,由該相乘一行(10)的尺寸。
  2. 將第二個偏移量(5)添加到結果中。
  3. 獲取該地址的內容。
1

如果有這樣

T a[N]; 

然後陣列的名稱被隱式轉換爲指向其除了極少數例外第一元件的陣列(如例如在sizeof操作者使用陣列名稱)。

因此,例如在表達式(a + 2)a是轉換類型T *的值&a[0]

相對於你的例子wuth陣列

int a[101][101]; 

在表達

a + 2 

一個被轉換成int (*)[101]類型並指向陣列的第一「行」的右值。 a + 2指向陣列的第三個「行」。該行的類型是int[101]

表達式*(a+2)給出了此第三行的類型爲int[101],這是一個數組。並且這個數組在表達式中依次被轉換爲它的第一個元素的指針int *

它與第三行佔用的內存區域的起始地址相同。

只有表達(a + 2)具有類型int (*)[101]而表達*(a + 2)具有類型int *。但是這兩者產生相同的值 - 數組的第三行佔用的內存區域的起始地址a

+0

謝謝!這非常有幫助。 – Shubham

0

數組的第一個元素與數組本身位於同一位置 - 數組中沒有「空白空間」。

cout << a + 2a被隱式轉換成一個指向它的第一元件,&a[0]a + 2a的第三元件,&a[2]的位置。

cout << *(a + 2)中,數組*(a + 2) - 即a[2] - 被轉換爲指向其第一個元素&a[2][0]的指針。

由於a的第三個元素的位置和a的第三個元素的第一個元素的位置相同,所以輸出是相同的。

0

我會盡力解釋你如何內存是由編譯器映射:

讓我們考慮一個更加之實踐例子多維數組:

int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; 

您可以執行命令

x/10w a 

在GDB中看看內存:

0x7fffffffe750: 1 2 3 4 
0x7fffffffe760: 5 6 7 8 
0x7fffffffe770: 9 0 

每個元素都存儲在一個int類型(32位/ 4字節)。 所以矩陣的第一個元素已被存儲在:

1) a[0][0] -> 0x7fffffffe750 
2) a[0][1] -> 0x7fffffffe754 
3) a[0][2] -> 0x7fffffffe758 
4) a[1][0] -> 0x7fffffffe75c 
5) a[1][1] -> 0x7fffffffe760 
6) a[1][2] -> 0x7fffffffe764 
7) a[2][0] -> 0x7fffffffe768 
     ... 

的命令:

std::cout << a + 2 << '\n' 

它將打印,因爲該 指針aritmetic的地址0x7fffffffe768: 類型的一個int **所以它是一個指向指針的指針。 a + 2是a [0](第一行)+2。結果是指向第三行的指針 。

*(A + 2)deferences第三行,這是{7,8,9}

第三行是int數組,這是爲int的指針。

然後運營商< <將打印該指針的值。

+0

在這個例子中,不是'a'實際上'int [3] [3]'的類型嗎? – wally

+0

@flatmouse你是對的。更準確的說這個類型是int [3] [3],這是因爲大小是靜態的,編譯時間。 –