2010-04-21 206 views
1

我有一個3x3數組,我試圖創建一個指針,並且我一直收到這個數組,給出了什麼?無法從int [] []轉換爲int *

我該如何定義指針?我嘗試了[]和*的各種組合。

可以做到這一點嗎?

int tempSec[3][3]; 

int* pTemp = tempSec; 
+0

這問題每天問10次左右,每次都回答。爲什麼這不關閉? – 2010-04-21 13:20:40

+0

您需要使用typedef來提供幫助。見下文。 – 2010-04-21 13:20:49

+0

提供重複的鏈接,我會投票結束它。 – Suma 2010-04-21 13:24:34

回答

15

你可以做int *pTemp = &tempSec[0][0];

如果你要治療一個3x3的陣列作爲一個int *,你應該宣佈它作爲一個int[9],並使用tempSec[3*x+y]代替tempSec[x][y]

另外,也許你想要的是int (*pTemp)[3] = tempSec?那將是一個指向tempSec的第一個元素的指針,第一個元素本身就是一個數組。

你其實可以採取一個指針到一個二維數組:

int (*pTemp)[3][3] = &tempSex; 

你會再使用這樣的:

(*pTemp)[1][2] = 12; 

這是幾乎可以肯定不是你想要的,但在你的評論你確實要求它...

+0

那麼這些是我的兩個選擇?沒有辦法創建一個指向2D數組的指針? – cam 2010-04-21 12:57:15

+3

是的,但它不會有'int *'類型。我不知道你問題的哪些部分是你想要的部分,哪些不是你想要的部分... – 2010-04-21 12:59:22

+1

這樣做,你扔掉任何關於數據佈局的信息。現在你不能說它是一個三乘三的數組。 – 2010-04-21 13:20:32

0
int a[20][30]; 
int* b=&a[0][0]; 
0

原帖如下 - 請忽略,它是誤導。留下它爲了後代的緣故;)

但是,here is a link I found regarding memory allocation of 2-dimensional arrays in c++。也許它可能更有價值。


不知道這是你想要的東西,它已經有一段時間,因爲我寫C++,但你的施法失敗的原因,是因爲你是從一個數組的數組去整型的指針。如果,另一方面,你從數組試圖數組指針的指針,它可能會工作

int tempSec[3][3]; 
int** pTemp = tempSec; 

記住,你的數組的數組是真正的內存持有指針的其他連續塊的鄰接塊內存 - 這就是爲什麼將一個數組數組轉換爲一個int數組會得到一個看起來像垃圾的數組[垃圾真的是內存地址!]。

再次,取決於你想要什麼。如果你想要它的指針格式,指針的指針是要走的路。如果你想要所有9個元素作爲一個連續的數組,你將不得不對你的double數組進行線性化處理。

+0

「你的數組陣列實際上是一塊連續的內存塊,指向其他連續的內存塊」。不,它確實不是。 – 2010-04-21 13:07:08

+0

「你的數組數組實際上是一個持有指針的連續塊內存」---在這種情況下,這是不真實的。一個聲明爲「int arr [3] [3]」的數組是一個連續的內存塊,足夠大的空間用於9個int,並通過計算出的偏移量進行訪問。我想很多C程序員都假設所有的多維數組都是指向指針的指針(等等......),因爲'char ** argv' ---但是請記住這是一個'char *'數組,即一個字符串數組。一般來說,只有「不齊」的多維數組被實現爲多層間接尋址(這是由程序員自行決定的)。 – 2010-04-21 13:09:56

+0

@Derrick土耳其,謝謝你的有益的意見!比我記得的更加生疏;) – 2010-04-21 13:26:54

0

正如史蒂夫指出的,正確的形式是int *pTemp = &tempSec[0][0];int** pTemp2 = tempSec;不起作用。給出的錯誤是:

cannot convert 'int (*)[3]' to 'int**' in initialization 

它沒有存儲爲指向數組的指針數組。它存儲爲一個大的矢量,編譯器隱藏你的[a][b] = [a*rowLength+b]

#include <iostream> 
using namespace std; 
int main() 
{ 
    // Allocate on stack and initialize. 
    int tempSec[3][3]; 
    int n = 0; 
    for(int x = 0; x < 3; ++x) 
     for(int y = 0; y < 3; ++y) 
      tempSec[x][y] = n++; 

    // Print some addresses. 
    cout << "Array base: " << size_t(tempSec) << endl; 
    for(int x = 0; x < 3; ++x) 
     cout << "Row " << x << " base: " << size_t(tempSec[x]) << endl; 

    // Print contents. 
    cout << "As a 1-D vector:" << endl; 
    int *pTemp = &tempSec[0][0]; 
    for(int k = 0; k < 9; ++k) 
     cout << "pTemp[" << k << "] = " << pTemp[k] << endl; 
    return 0; 
} 

輸出:

Array base: 140734799802384 
Row 0 base: 140734799802384 
Row 1 base: 140734799802396 
Row 2 base: 140734799802408 
As a 1-D vector: 
pTemp[0] = 0 
pTemp[1] = 1 
pTemp[2] = 2 
pTemp[3] = 3 
pTemp[4] = 4 
pTemp[5] = 5 
pTemp[6] = 6 
pTemp[7] = 7 
pTemp[8] = 8 

注意,行0的地址是相同的完整的陣列地址,以及連續的行由sizeof(int) * 3 = 12抵消。 easyier

6

它使用一個typedef

typedef int ThreeArray[3]; 
typedef int ThreeByThree[3][3]; 

int main(int argc, char* argv[]) 
{ 
    int   data[3][3]; 

    ThreeArray* dPoint = data; 
    dPoint[0][2]   = 5; 
    dPoint[2][1]   = 6; 

    // Doing it without the typedef makes the syntax very hard to read. 
    // 
    int(*xxPointer)[3] = data; 
    xxPointer[0][1]  = 7; 

    // Building a pointer to a three by Three array directly. 
    // 
    ThreeByThree* p1  = &data; 
    (*p1)[1][2]   = 10; 

    // Building a pointer to a three by Three array directly (without typedef) 
    // 
    int(*p2)[3][3]  = &data; 
    (*p2)[1][2]   = 11; 

    // Building a reference to a 3 by 3 array. 
    // 
    ThreeByThree& ref1 = data; 
    ref1[0][0]   = 8; 

    // Building a reference to a 3 by 3 array (Without the typedef) 
    // 
    int(&ref2)[3][3]  = data; 
    ref2[1][1]   = 9; 


    return 0; 
} 
+0

這會丟棄數組的其中一個維度,這正是您在我的答案中指出的。所以現在我很困惑你在做什麼。 – 2010-04-21 13:27:35

+0

@Steve Jessop:你放棄了這兩個維度。我只丟棄一個。轉換爲一個指針,你將鬆散一個維度,你不能幫助。如果我們轉換爲引用,那麼您不需要鬆散維度。 – 2010-04-21 13:32:41

+0

除了我的答案的第一行之外,我給出了和你一樣的答案,但沒有使用typedef。無論如何,你可以*避免丟失任何維度,將所有維度都包含在指針的類型中。這不太可能是提問者想要的,但是對於我來說,提問者是特別想要一個'int *',還是隻想要某種指向數組的指針,這是完全不清楚的。這就是我提到兩者的原因。 – 2010-04-21 13:36:07

0

另一種方式去這樣做,是先創建一個指針數組:

int* pa[3] = { temp[0], temp[1], temp[2] }; 

然後創建一個指向指針指向:

int** pp = pa; 

然後,您可以使用該指針指針的普通數組語法來獲取您的元素Ë尋找:

int x = pp[1][0]; // gets the first element of the second array 

另外,如果你想將其轉換爲指針的唯一原因是這樣你就可以把它傳遞給一個函數,你可以這樣做:

void f(int v[3][3]); 

由於只要數組的大小是固定的,您可以將二維數組傳遞給像這樣的函數。它比比傳遞指針更具體。

+0

這個'f'的簽名是不是真的放棄了其中一個維度?它與void f(int(* v)[3]);'的同義,',實際上是指向數組的指針而不是數組。所以雖然它比傳遞一個int **更具體,但並不像你想象的那樣具體。將數字放在最後一個維度是有點誤導的,因爲編譯器會忽略它,但這是調用者想要傳遞的數組數量的一個線索。 – 2010-04-21 13:50:30

+0

在哪裏按最後尺寸,當然我的意思是第一維... – 2010-04-21 13:57:08

+0

很明顯,編譯器會讓你做各種瘋狂的事情而不抱怨。是的,我的觀點是,這對用戶來說會更加清楚。 – 2010-04-21 13:58:49

3

哦。這很容易!

int aai[3][3]; 
int* pi = reinterpret_cast<int*>(aai); 

實際上,您可以使用這種令人敬畏的技巧將其轉換爲其他精彩的類型。例如:

int aai[3][3]; 
int (__stdcall *pfi_lds)(long, double, char*) = reinterpret_cast<int (__stdcall *)(long, double, char*)>(aai); 

是不是隻是膨脹?問題是它是否有意義。

你在問怎麼騙你的編譯器。所以首先要知道的是:你爲什麼要撒謊?

+0

是的,這真的不是一個好主意...... – 2010-04-21 13:38:45

+0

你爲什麼要這樣做?獲得第一個成員的地址是完全合法的。 – 2010-04-21 14:23:32

0

讓我們問cdecl.org翻譯您的聲明我們:

int tempSec[3][3] 

回報

declare tempSec as array 3 of array 3 of int 


好了,我們如何創建一個指向?讓我們CDECL又問:

declare pTemp as pointer to array 3 of array 3 of int 

回報

int (*pTemp)[3][3] 


既然我們已經有一個整型數組3的排列3,我們可以這樣做:

int (*pTemp)[3][3] = &tempSec;