How do you allocate and declare a 3D array of structs in C? Do you first allocate the array or declare it? I feel like you have to allocate it first so you can declare it so it is on the heap, but then how do you allocate something that hasn't been made yet? Also, should you allocate it all at once or element by element? Also am i putting the structs into the array correctly? My guess on how to do it would be:
如何在C中分配和声明结构的3D数组?你首先分配数组还是声明它?我觉得你必须首先分配它,这样你就可以声明它,因为它在堆上,但那么你如何分配尚未制作的东西呢?另外,您应该一次性还是逐个元素地分配它?我也正确地将结构放入数组中?我对如何做的猜测是:
header.h
header.h
struct myStruct{
int a;
int b;
};
typedef struct myStruct myStruct_t;
main.c
main.c中
#include "header.h"
#include <stdio.h>
#include <stdlib.h>
int main(void){
int length=2;
int height=3;
int width =4;
myStruct_t *elements;
struct myStruct arr = (*myStruct_t) calloc(length*height*width, sizeof(myStruct);
//zero based array
arr[length-1][height-1][width-1];
int x=0;
while(x<length){
int y=0;
while(y<height){
int z=0;
while(z<depth){
arr[x][y][z].a=rand();
arr[x][y][z].b=rand();
z++;
}
y++;
}
x++;
}
return 0;
}
2 个解决方案
#1
1
The easy way is:
简单的方法是:
myStruct_t (*arr2)[height][width] = calloc( length * sizeof *arr );
Then your loop can access arr2[x][y][z].a = rand();
and so on. If you're not familiar with this way of calling calloc
, see here. As usual with malloc, check arr2
against NULL
before proceeding.
然后你的循环可以访问arr2 [x] [y] [z] .a = rand();等等。如果您不熟悉这种调用calloc的方法,请参阅此处。像往常一样使用malloc,在继续之前检查arr2是否为NULL。
The triple-pointer approach is not really a practical solution. If your compiler does not support variably-modified types then the array should be flattened to 1-D.
三指针方法实际上并不是一个实用的解决方案。如果编译器不支持可变修改类型,则应将数组展平为1-D。
#2
1
There are a couple of different ways to do this, depending on what you want. First, you can allocate your array on the stack (in C99 and some compilers) like this:
根据您的需要,有几种不同的方法可以做到这一点。首先,您可以在堆栈上分配您的数组(在C99和一些编译器中),如下所示:
myStruct_t arr[length][height][depth];
If you want it allocated on the heap, then you can do a single allocation of the appropriate size. You can then either do the index calculation yourself or make a pointer do the work for you (in C99 and some compilers):
如果您希望在堆上分配它,那么您可以执行适当大小的单个分配。然后,您可以自己进行索引计算,也可以使指针为您完成工作(在C99和一些编译器中):
void *buf = malloc(length * height * width * sizeof(myStruct_t));
myStruct_t *arr = buf;
myStruct_t (*arr2)[height][width] = buf;
/* TODO: check return of malloc */
...
arr[x * height * width + y * width + z].a = rand(); /* indexing the C89 way */
arr2[x][y][z].b = rand(); /* indexing the C99 way */
Or you can manually allocate the multiple dimensions.
或者您可以手动分配多个维度。
#include <stddef.h>
#include <stdlib.h>
typedef struct myStruct
{
int a, b;
} myStruct_t;
int main()
{
myStruct_t ***arr;
int length = 5000, height = 1000, depth = 20;
int x, y, z;
int ret = 1;
if (NULL == (arr = malloc(length * sizeof(myStruct_t**))))
goto FAIL;
for (x = 0; x < length; ++x)
{
if (NULL == (arr[x] = malloc(height * sizeof(myStruct_t*))))
goto FAIL_X;
for (y = 0; y < height; ++y)
{
if (NULL == (arr[x][y] = malloc(depth * sizeof(myStruct_t))))
goto FAIL_Y;
for (z = 0; z < depth; ++z)
{
arr[x][y][z].a = rand();
arr[x][y][z].b = rand();
}
}
}
/* TODO: rest of program logic */
/* program successfully completed */
ret = 0;
/* reclaim arr */
FAIL_CLEANUP: /* label used by TODO code that fails */
for (x = length - 1; x >= 0; --x)
{
for (y = height - 1; y >= 0; --y)
{
free(arr[x][y]);
FAIL_Y:
;
}
free(arr[x]);
FAIL_X:
;
}
free(arr);
FAIL:
return ret;
}
This last version uses a lot more memory for all the explicit pointers it contains, its memory locality is worse and it's significantly more complex to properly allocate and reclaim. However, it does allow different sizes along your dimensions. For example, the array arr[0][4]
can have a different size than arr[0][7]
if you ever need that.
最后一个版本为它包含的所有显式指针使用了更多的内存,它的内存局部性更差,并且正确分配和回收它要复杂得多。但是,它确实允许您的尺寸不同的尺寸。例如,如果您需要,阵列arr [0] [4]可以具有与arr [0] [7]不同的大小。
If you want to allocate it on the heap, then you probably want the second version with a single allocation and multi-dimension pointer (if available) or do the indexing yourself manually using appropriate math.
如果要在堆上分配它,那么您可能希望第二个版本具有单个分配和多维指针(如果可用),或者使用适当的数学手动自己编制索引。
#1
1
The easy way is:
简单的方法是:
myStruct_t (*arr2)[height][width] = calloc( length * sizeof *arr );
Then your loop can access arr2[x][y][z].a = rand();
and so on. If you're not familiar with this way of calling calloc
, see here. As usual with malloc, check arr2
against NULL
before proceeding.
然后你的循环可以访问arr2 [x] [y] [z] .a = rand();等等。如果您不熟悉这种调用calloc的方法,请参阅此处。像往常一样使用malloc,在继续之前检查arr2是否为NULL。
The triple-pointer approach is not really a practical solution. If your compiler does not support variably-modified types then the array should be flattened to 1-D.
三指针方法实际上并不是一个实用的解决方案。如果编译器不支持可变修改类型,则应将数组展平为1-D。
#2
1
There are a couple of different ways to do this, depending on what you want. First, you can allocate your array on the stack (in C99 and some compilers) like this:
根据您的需要,有几种不同的方法可以做到这一点。首先,您可以在堆栈上分配您的数组(在C99和一些编译器中),如下所示:
myStruct_t arr[length][height][depth];
If you want it allocated on the heap, then you can do a single allocation of the appropriate size. You can then either do the index calculation yourself or make a pointer do the work for you (in C99 and some compilers):
如果您希望在堆上分配它,那么您可以执行适当大小的单个分配。然后,您可以自己进行索引计算,也可以使指针为您完成工作(在C99和一些编译器中):
void *buf = malloc(length * height * width * sizeof(myStruct_t));
myStruct_t *arr = buf;
myStruct_t (*arr2)[height][width] = buf;
/* TODO: check return of malloc */
...
arr[x * height * width + y * width + z].a = rand(); /* indexing the C89 way */
arr2[x][y][z].b = rand(); /* indexing the C99 way */
Or you can manually allocate the multiple dimensions.
或者您可以手动分配多个维度。
#include <stddef.h>
#include <stdlib.h>
typedef struct myStruct
{
int a, b;
} myStruct_t;
int main()
{
myStruct_t ***arr;
int length = 5000, height = 1000, depth = 20;
int x, y, z;
int ret = 1;
if (NULL == (arr = malloc(length * sizeof(myStruct_t**))))
goto FAIL;
for (x = 0; x < length; ++x)
{
if (NULL == (arr[x] = malloc(height * sizeof(myStruct_t*))))
goto FAIL_X;
for (y = 0; y < height; ++y)
{
if (NULL == (arr[x][y] = malloc(depth * sizeof(myStruct_t))))
goto FAIL_Y;
for (z = 0; z < depth; ++z)
{
arr[x][y][z].a = rand();
arr[x][y][z].b = rand();
}
}
}
/* TODO: rest of program logic */
/* program successfully completed */
ret = 0;
/* reclaim arr */
FAIL_CLEANUP: /* label used by TODO code that fails */
for (x = length - 1; x >= 0; --x)
{
for (y = height - 1; y >= 0; --y)
{
free(arr[x][y]);
FAIL_Y:
;
}
free(arr[x]);
FAIL_X:
;
}
free(arr);
FAIL:
return ret;
}
This last version uses a lot more memory for all the explicit pointers it contains, its memory locality is worse and it's significantly more complex to properly allocate and reclaim. However, it does allow different sizes along your dimensions. For example, the array arr[0][4]
can have a different size than arr[0][7]
if you ever need that.
最后一个版本为它包含的所有显式指针使用了更多的内存,它的内存局部性更差,并且正确分配和回收它要复杂得多。但是,它确实允许您的尺寸不同的尺寸。例如,如果您需要,阵列arr [0] [4]可以具有与arr [0] [7]不同的大小。
If you want to allocate it on the heap, then you probably want the second version with a single allocation and multi-dimension pointer (if available) or do the indexing yourself manually using appropriate math.
如果要在堆上分配它,那么您可能希望第二个版本具有单个分配和多维指针(如果可用),或者使用适当的数学手动自己编制索引。