分配6xNxNarrays
我有一个变量N
我需要一个6xNxN
arrays。
像这样的东西:
int arr[6][N][N];
但是,显然,这不起作用。
我不知道如何分配这个以便我可以访问,例如arr[5][4][4]
如果N
是5,而arr[5][23][23]
如果N
是24 。
请注意, N
永远不会改变,所以我永远不必重新分配realloc
arr
。
我该怎么办? 将int ***arr = malloc(6 * N * N * sizeof(int));
工作?
对此行中的声明进行简单更改并保留malloc
可以轻松解决您的问题。
int ***arr = malloc(6 * N * N * sizeof(int));
但是, int ***
是不必要的(也是错误的)。 使用易于分配的平面arrays:
int *flatarr = malloc(6 * N * N * sizeof(int));
这适用于三维,而不是像问题中那样访问arr[X][Y][Z]
,而是访问flatarr[(X*N*N) + (Y*N) + Z]
。 事实上,你甚至可以编写一个方便的宏:
#define arr(X,Y,Z) flatarr[((X)*N*N) + ((Y)*N) + (Z)]
这基本上是我在我的语言中用立体方式完成的,以允许多尺寸的立方体。 感谢Programming Puzzles和Code Golf用户Dennis给了我这个想法。
您可以在堆上分配三维数组
int (*arr)[N][N] = malloc(sizeof(int[6][N][N]));
使用后,您可以免费使用
free(arr);
另一种写@StoryTeller建议的方式是 –
int (*arr)[N][N] = malloc(6u * sizeof(*arr));
但是在这里你需要注意6
后的u
以防止带符号的算术溢出。
此外,在平台上仍然存在问题,其中size_t
宽度小于@chqrlie建议的int,但在“大多数”常用平台上情况并非如此,因此您可以正常使用它。
int arr[6][N][N];
会工作得很好。 您只需将编译器和C知识更新到1999或更高版本,当时将可变长度数组(VLA)引入该语言。
(如果您的GCC版本低于5.0,则必须通过传递-std=c99
或-std=c11
明确告诉它不要使用古老版本的C标准。)
或者,如果您需要堆分配,您可以:
int (*arrptr)[Y][Z] = malloc( sizeof(int[X][Y][Z]) );
你不能做int ***arr = malloc(6 * N * N * sizeof(int));
因为int***
不能指向3D数组。 一般来说,两个以上的间接级别是您的程序设计完全存在缺陷的一个标志。
详细信息: 正确分配多维数组 。
你想要什么不能直接工作。 对于索引多维数组,除了第一个维度之外的所有维度都需要是类型的一部分,这就是为什么:
索引操作符通过首先向指针添加索引然后解除引用来对指针进行操作。 数组的标识符计算为指向其第一个元素的指针(例如,与sizeof
, _Alignof
和&
一起使用时除外),因此对数组的索引按预期工作。
在单维数组的情况下,它非常简单。 同
int a[42];
a
求值为int *
类型的指针,索引按以下方式工作: a[18] => *(a + 18)
。
现在在一个二维数组中,所有元素都是连续存储的(“row”之后的“row”如果你想把它理解为一个矩阵),那么使索引“魔术”工作的是所涉及的类型 。 举个例子:
int a[16][42];
这里,a的元素的类型为int ()[42]
(int元素的42个元素)。 根据上面的规则,在大多数上下文中再次计算此类型的表达式会产生一个int *
指针。 但是它本身呢? 好吧,它是一个int ()[42]
数组,所以a
将计算一个指向42元素int : int (*)[42]
的指针 。 然后让我们看一下索引操作符的作用:
a[3][18] => *(*(a + 3) + 18)
通过计算类型为int (*)[42]
,这个内部添加3
可以正确地添加42 * sizeof(int)
。 如果在类型中不知道第二维,则这是不可能的。
我想推断出n维情况的例子很简单。
在您的情况下,您有两种可能性来实现类似于您想要的东西。
-
使用动态分配的大小为
6*N*N
平面arrays。 如果你在某处保存N
你可以自己计算指数。 -
效率稍低,但产生更好的可读代码,你可以使用一个指针数组的指针数组 (多个间接)。 你可以这样做
int ***a = malloc(6 * sizeof *int); for (size_t i = 0; i < 6; ++i) { a[i] = malloc(N * sizeof *(a[i])); for (size_t j = 0; j < N ++j) { a[i][j] = malloc(N* sizeof *(a[i][j])); } } // add error checking to malloc calls!
然后你的访问看起来就像普通的3d数组那样,但它存储在内部尽可能多的数组,指针指向其他数组而不是大的连续块。
我不认为使用这么多的间接值是值得的,只是为了避免写入例如
a[2*N*N+5*N+4]
来访问2,5,4
的元素,所以我的推荐是第一种方法。