2010-08-26 111 views
3

我一直在研究C++進行測試,目前我正在使用指針算術。指針算術幫助

的基本問題是以下內容:

int numColumns = 3; 
int numRows = 4; 

int a[numRows][numColumns]; 

a[0][0] = 1; 
a[0][1] = 2; 
a[0][2] = 3; 
a[1][0] = 4; 
a[1][1] = 5; 
a[1][2] = 6; 
a[2][0] = 7; 
a[2][1] = 8; 
a[2][2] = 9; 
a[3][0] = 10; 
a[3][1] = 11; 
a[3][2] = 12; 

for (int i=numColumns-1; i>-1;i--) 
{ 
    cout << a[numRows-1][i] << endl; 
} 

一個非常簡單的程序,它打印低級「的矩陣的行」。即12,11,10。

現在我試圖做一個int *的等價物。

我已經通過我的同學說是認爲它是這樣的:

array[i][j] == p[numColumns*i+j] 

如果這是正確的,不應該下面是相當於什麼我在尋找:

int* p = reinterpret_cast<int*> a; 
for (int i=numColumns-1; i>-1;i--) 
{ 
    cout << p[numColumns*(numRows-1)+i] << endl; 
} 

謝謝。

+1

你試過了嗎? – Beta 2010-08-26 19:15:27

+1

歡迎來到SO!感謝您告訴我們您正在學習考試。我爲你的問題添加了「家庭作業」標籤。你以很好的方式提出這些問題。 – John 2010-08-26 19:15:29

回答

2

int array[3][5]不是int array[3*5]的抽象(在C++語言中)。該標準說,一個2維數組(通常是N維數組)是數組的數組。 array[3][5]是一個由三個元素組成的數組,其中每個元素都是一個包含5個元素(在這種情況下爲整數)的數組。 C++的類型系統確實做出了區分。

根據C++標準,數組T array[N]是一個連續的內存塊,包含T型的N個元素。所以這意味着一個多維數組,比如int array [3] [5]將是一個包含3個int[5]數組的連續內存塊,並且每個int[5]數組都是一個連續的塊,其編號爲5 ints

在我的機器上,內存最終佈局與您預期的完全相同 - 與int array[3*5]完全相同。然而,由於類型系統(區分int[]int[][]),內存的處理方式不同。這就是爲什麼你需要使用reinterpret_cast,它基本上告訴你的編譯器「拿這個內存,不做任何轉換,把它當作這種新類型」。

但我不完全確定這個內存佈局是否有保證。我找不到標準中的任何內容,說明不能填充數組。如果它們可以被填充(再次,我不確定),那麼int[5]數組實際上可能不是5個元素長(更好的例子是char[5],我可以看到它被填充到8個字節)。

同樣在int*int**之間存在明顯的差異,因爲後者不保證連續的存儲器。

編輯:C++區分int[3*5]int[3][5]的原因是因爲它想要保證內存中元素的順序。在C++中int[0][1]int[0][2]分別是sizeof(int)。但是在Fortran中,例如,int[0][0]int[1][0]分別爲sizeof(int),因爲Fortran使用列主要表示。

這裏有一個圖,以幫助解釋:

0 1 2 
3 4 5 
6 7 8 

可以做成一個數組,看起來像{} 0,1,2,3,4,5,6,7,8或數組看起來像:{0,3,6,1,4,7,2,5,8}。

1

提示:在您的原始代碼中,a的類型更類似於int**,因此您不應該將其轉換爲int*。它是一個指針指向的東西。

如果你想像一維數組那樣訪問它,那麼a也必須被定義爲一維數組。

+0

真的嗎?我認爲多維數組對我們來說只是一個「抽象」,因爲以下是等價的: int array [3] [5]; int數組[3 * 5]; – 2010-08-26 19:34:45

0

@rwong:真的嗎?我認爲多dimensionals陣列只是一個「抽象」對我們來說,因爲下面是等價的:

int array[3][5]; 
int array[3*5]; 

不管怎麼說,我detemined什麼是錯的。像往常一樣,這不是我的代碼,而是複製粘貼某人的代碼並從那裏開始工作。

我有什麼是這樣的:

for(int i=numRows-1; i>-1 ;i++) 
{ 
    cout << p[numColumns*numRows-1+i] << endl; 
} 

很有趣,因爲我沒有複製粘貼VS我的代碼,但實際上寫了它從無到有「說明」我的錯誤。

課在這裏學到;)

編輯:我仍然不知道什麼rwong這裏解釋。有人會關心詳細說明嗎?

+0

我相信你在考慮定期的C,而不是C++。在常規C中,int a [rows] [cols]; int * b =(int *)a; a [x] [y] == b [x * cols + y];'會返回true。 – bta 2010-08-26 21:30:30

+0

rwong所說的是,嚴格來說,'a [x] [y]'中的'a'是一個指針指針(或者'int **')。第一維('a [x]')的項是'int *',不一定是一個數組。你可以有一個指向動態分配數組的指針數組。在這種情況下,您可以像「a [x] [y]」那樣對「矩陣」進行索引,但行並不一定在內存中連續,因此語法'a [x * cols + y]'很可能不起作用。 – bta 2010-08-26 21:37:33

0

另一種方式來想一想:既然a是類似於int**,是那裏a的一部分,它類似於一個int*

+0

等一分鐘。現在我更加困惑。
我所知道的是,數組的標識符相當於它的第一個元素的地址,所以指針和數組是相同的概念。
如果這是真的,多維數組只是程序員的一個抽象,編譯器會記住每個「維度」的深度,那麼矩陣如何等價於一個int **? 我錯過了什麼嗎? – 2010-08-26 19:51:31

+0

是的。在C++中int [] []不是int []的抽象。 int [] []是它自己的類型。原因是C++是一種主要的語言。 int []允許您使用行或列主佈局。例如,您可以執行p [y * width + x](行主要)或p [x * height + y](列主要)。在C++中int [x] [y]總是p [y * width + x]。 – 2010-08-26 20:53:57