2017-06-19 48 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数组。