[英]C++ multidimensional array and pointers to table of pointers
這是東西。 我可以完全理解由指向數組的指針等組成的多維數組的概念(讓我們考慮一下二維)。
我們做這樣的事情:
// we can use dynamically defined size n and m
int n = 3, m = 5 ;
int **T = new int *[n];
for (int i = 0 ; i < n ; ++i)
T[i] = new int[m];
我們得到的是:(檢查我是否在這里)
現在的問題是,當我們這樣做時:
int n = 3, m = 5 ;
int T[n][m] ;
我們所能做的並不是我以前展示過的事情。 我們有些奇怪。 什么是T? 當打印T時,我們得到與T [0]相同的值。 似乎我們保留了一個大小為n * m的整數塊,而沒有指向行的附加指針數組。
我的問題是:編譯器會記住數組的維數以及行和列的數量嗎? 當要求T [i] [j]時,實際上要求的是*(T + i * n + j),所以這n存儲在某個地方嗎? 問題是當我們試圖將此東西(T)傳遞給函數時。 我不知道為什么,但是如果n和m是常量,則可以將T作為指向此數組的指針傳遞,以使其在此程序中起作用:
#include <stdio.h>
const int n = 3, m = 4 ; // this is constant!
void add_5(int K[][m])
{
for (int i = 0 ; i < n ; ++i)
for (int j = 0 ; j < m ; j++)
K[i][j] += 5 ;
}
int main()
{
// n x m array the most straight forward method
int T[n][m] ;
for (int i = 0 ; i < n ; ++i)
for (int j = 0 ; j < m ; ++j)
T[i][j] = i*m + j ;
for (int i = 0 ; i < n ; ++i)
{
for (int j = 0 ; j < m ; j++)
printf("%d ",T[i][j]) ;
printf("\n") ;
}
printf("\n") ;
// adding 5 to all cells
add_5(T) ;
printf("it worked!!\n") ;
for (int i = 0 ; i < n ; ++i)
{
for (int j = 0 ; j < m ; j++)
printf("%d ",T[i][j]) ;
printf("\n") ;
}
int ss ;
scanf("%d",&ss) ;
}
但是,如果n和m不是常數,我們就不能。 因此,我需要的是將動態創建的多維數組的指針傳遞給函數,而無需為此手動分配內存。 這個怎么做?
在C ++中,數組實際上是指向內存塊的指針
絕對不。 數組與指針完全分開。 您可能會感到困惑的原因是由於稱為數組到指針轉換的標准轉換。 考慮:
int arr[10];
變量arr
表示一個數組。 根本不是指針。 碰巧的是,在許多情況下,數組的名稱將轉換為指向其第一個元素的指針。 也就是說,轉換將其轉換為int*
。
int T[n][m] ;
在這種情況下, T
是“ m
int
的n
數組的數組”。 您提到打印T
和T[0]
得到相同的結果,這是由於數組到指針的轉換所致。
表達式T
可以轉換為指向第一個元素的指針; 也就是int (*)[m]
,因為T
的第一個元素本身就是一個包含m
元素的數組。
表達式T[0]
可以轉換為指向第一個子數組的第一個元素的指針。 因此,您獲得了一個指向int*
類型的元素T[0][0]
的指針。
由於數組在內存中的布局方式,這些指針具有相同的地址。 數組開始的地址與該數組的第一個元素的地址相同。 但是,指針的行為方式不同。 如果增加由T
產生的指針,則移至下一個子數組。 如果遞增由T[0]
得出的指針,則移至下一個int
。
與動態分配的“ 2D數組”相比,它可能有助於您查看內存中2D數組的布局圖。 3×3 2D數組如下所示:
0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ int │ int │ int │ int │ int │ int │ int │ int │ int │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
而如果您動態分配了一個3×3的“ 2D數組”:
┌─────┐
│ │ // The int**
└──╂──┘
┃
▼
┌─────┬─────┬─────┐
│ │ │ ┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ // An array of int*
└──╂──┴──╂──┴─────┘ ┃
┃ ┗━━━━━━━━━━━━━━━┓ ┃
▼ ▼ ▼
┌─────┬─────┬─────┐ ┌─────┬─────┬─────┐ ┌─────┬─────┬─────┐
│ int │ int │ int │ │ int │ int │ int │ │ int │ int │ int │ // Arrays of ints
└─────┴─────┴─────┘ └─────┴─────┴─────┘ └─────┴─────┴─────┘
0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2
編譯器是否還記得數組的尺寸以及行和列的數量?
是的,如果您具有數組類型的變量,則數組的大小就是該類型的一部分。 編譯器始終知道變量的類型。
當要求T [i] [j]時,實際上要求的是*(T + i * n + j),所以這n存儲在某個地方嗎?
表達式T[i][j]
等於*(*(T + i) + j)
。 讓我們了解它的作用。 首先,由T
進行數組到指針的轉換,得到int (*)[m]
。 然后,我們將i
添加到此以指向第i
個子數組。 然后將其取消引用以獲取子數組。 接下來,此子數組也將進行數組到指針的轉換,得到一個int*
。 然后,向其添加j
以獲得指向該子數組中第j
個int
對象的指針。 取消引用以提供該int
。
問題是當我們試圖將此東西(T)傳遞給函數時。 我不知道為什么,但是如果n和m是常量,則可以將T作為指向此數組的指針傳遞給函數
這實際上是謊言。 您沒有將2D數組傳遞給函數。 實際上,沒有像數組類型這樣的參數。 您的參數int K[][m]
實際上等效於int (*K)[m]
。 也就是說,所有數組類型參數都轉換為指針。
因此,當您使用add_5(T)
調用此函數時,沒有傳遞T
表示的數組。 T
實際上正在進行數組到指針的轉換,以為您提供一個int (*)[m]
並且此指針正在傳遞到函數中。
這是二維動態數組的示例:
const int Mapsize = n
int** GameField2 = 0;
GameField2 = new int*[Mapsize]; // memory alocation
for(int i = 0; i < Mapsize; i++)
GameField2[i] = new int[Mapsize];
for(int j = 0; j < Mapsize; j++)
for(int i = 0; i < Mapsize; i++)
GameField2[i][j] = 0;
如果您希望在任何函數上對該數組進行操作,只需傳遞如下指針:
int Whatver(int** GameField)
{
GameField[a][b]=x;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.