2017-06-19 52 views
0

我試圖製作一個使用二維數組作爲其級別基礎的遊戲。但是,它的大小需要能夠在不同層次上變化。 經過一番研究,我發現this question似乎與我有同樣的問題。我試過儘可能地應用它:在結構中的多維動態數組,大小由int在同一個struct中定義的大小C

typedef struct level{ 

    /*other stuff*/ 
    int Size; 
    int Arr[0][0]; 

}level; 

level InitLevel(int S){ 
struct level* N = malloc(sizeof(level)+S*S*sizeof(int)); 
N->Size=S; 
int i,j; 
for(i=0;i<S;i++){ 
    for(j=0;j<S;j++){ 
    N->Arr[i][j]=0; 
    } 
} 
return *N; 
} 

編譯得很好,所以就是這樣。問題是,在主一次,看起來大約是這樣的:

int main(){ 
    level myLevel = InitLevel(10); 
    printf("%i \n",myLevel.Size); 
    printf("%i \n",myLevel.Arr[5][5]); 
} 

雖然myLevel.Size返回正確的值,原來數組的值不正確地設置爲0,而不是返回似乎是要麼胡言亂語或記憶地址。

我不確定我做錯了什麼,但我希望我離解決方案不遠?幫助將不勝感激。

+0

'int arr [0] [0];'停在這裏。刪除這一行。 C中的數組不以這種方式工作。鏈接問題中的什麼讓你相信你可以做到這一點? –

+0

'N = malloc(...);返回* N'; C中的動態分配也不會以這種方式工作。 –

回答

0

這不能工作;你似乎期待編譯器只是奇蹟般地認識到Arr成員的大小是由它之前的成員控制的。這在代碼的任何地方都沒有說過(因爲它不可能說),所以它怎麼可能呢?

這顯然:

N->Arr[i][j] = 0; 

將不得不計算在其中存儲0和實際內存位置,要做到這一點,需要兩兩件事:

  • 一個的大小「行」的陣列的
  • 一項的大小‘陣列

後者的元件’是衆所周知(它是int),但前者是0。對於一維數組,上面的第一個點消失了,這就是爲什麼索引可以工作,因爲它只是使用衆所周知的元素大小。

你需要自己做的地址計算,並刪除「神奇」 0尺寸的想法:

typedef struct level { 
    /*other stuff*/ 
    int Size; 
    int *Arr; // Size x Size 2D array. 
}level; 

然後做像這樣的訪問:

N->arr[i * S + j] = 0; 

當然,這也意味着level不是值類型,因爲其中不包含Arr。您可以將它包含在堆分配中,但是您仍然不能將其分配,因爲Arr所需的內存不會被複制。

0

首先,您不能通過值返回動態分配的結構。如果你嘗試,你的結構將被分割,這意味着你將只複製Arr的第一個元素,並且會產生內存泄漏,因爲分配的內存將永遠不會被釋放:您必須返回一個指針,然後釋放。

你必須要處理你的動態二維數組。一個是由@unwind提出的,由一個具有顯式索引計算的1D數組組成。它非常高效,但不幸的是不允許你使用2D慣用的[i][j]

另一種方法是使用指針數組。您分配陣列本身的Size * Size整數指針的數組,每個指針指向行的開始。它可能效率較低,因爲它使用指針數組和額外的間接索引來代替直接索引,但您可以使用慣用的2D訪問。如果你可以肯定的是指針的對齊要求大於或等於int(*)的一個,你可以這樣做:

typedef struct level{ 
    /*other stuff*/ 
    int Size; 
    int **Arr; 
}level; 
level* InitLevel(int S){ 
    struct level* N = malloc(sizeof(level)+S*sizeof(int *) + S*S*sizeof(int)); 
    N->Size=S; 
    int i,j; 
    int *arr = (void *) N->Arr[Size]; // immediately after the array of pointers 
    for(i=0;i<S;i++){ 
     N->Arr[i] = arr + i *Size; 
     for(j=0;j<S;j++){ 
      N->Arr[i][j]=0;   // correct access 
     } 
    } 
    return N; 
} 

你的主要變爲:

int main(){ 
    level* myLevel = InitLevel(10); 
    printf("%i \n",myLevel->Size); 
    printf("%i \n",myLevel->Arr[5][5]); 
    free(myLevel); 
    return(0); 
} 

(*)通常,應該爲指針和整數數組分別分配一個數組。但是,如果對int指針的對齊要求比int指針要嚴格,則可以在指針數組之後立即使用存儲器來存儲int數組。