结构中的多维动态数组,大小由C中同一结构中的int定义

结构中的多维动态数组,大小由C中同一结构中的int定义,c,arrays,multidimensional-array,struct,malloc,C,Arrays,Multidimensional Array,Struct,Malloc,我正在尝试制作一个游戏,使用2D数组作为其级别的基础。但是,它的大小需要能够因级别而异。 经过一番研究,我发现这似乎和我有同样的问题。我已尽我所能尝试应用它: 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-

我正在尝试制作一个游戏,使用2D数组作为其级别的基础。但是,它的大小需要能够因级别而异。 经过一番研究,我发现这似乎和我有同样的问题。我已尽我所能尝试应用它:

 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;
}
虽然myLevel.Size返回正确的值,但结果表明数组的值没有正确设置为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
所需的内存。

首先,您不能通过值返回动态分配的结构。如果您尝试,您的结构将被切片,这意味着您将只复制
Arr
的第一个元素,并且将发生内存泄漏,因为分配的内存永远不会被释放:您必须返回指针,稍后再释放

您必须找到处理动态二维阵列的方法。一个由@unwind提出,由一个一维数组组成,带有显式索引计算。它非常有效,但不幸的是不允许您使用2D惯用
[i][j]

另一种方法是使用指针数组。您分配数组本身的
Size
*
Size
ints
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的指针的对齐要求比指向int的指针的对齐要求更严格,则可以使用指针数组之后立即开始的存储来存储int数组。

int Arr[0][0]停在这里。删除这一行。C中的数组不是这样工作的。链接问题中的什么让你相信你能做到这一点;返回*N
;C中的动态分配也不是这样工作的。
 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);
}