Mik*_*ike 28 c arrays multidimensional-array
我正在将一些MATLAB代码翻译成C,我正在转换的脚本大量使用具有10*100*300复杂条目的3D数组.数组的大小也取决于传感器的输入,理想情况下应该动态分配数组.到目前为止,我已经尝试了两种方法,第一种方法是平面1D阵列
value = array[x + (y*xSize) + (z*ySize*xSize)]
Run Code Online (Sandbox Code Playgroud)
哪会伤害我的大脑使用.我还尝试了一个指针数组的数组
int main () {
int ***array = malloc(3*sizeof(int**));
int i, j;
for (i = 0; i < 3; i++) {
*array[i] = malloc(3*sizeof(int*));
for (j = 0; j < 3; j++) {
array[i][j] = malloc(3*sizeof(int));
}
}
array[1][2][1] = 10;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我尝试分配数据时,会出现seg错误.
在一个完美的世界中,我想使用第二种方法和数组符号来实现更清晰,更简单的编程.有没有更好的方法在C中动态分配三维数组?
tim*_*tes 18
我会选择第一个选项(单个1D阵列),因为它会为你提供一个单独的内存块,而不是潜在的数千个碎片内存块
如果访问数组的正确元素正在努力,我会写一个实用工具方法将x,y,z位置转换为1D数组的偏移量
int offset(int x, int y, int z) {
return (z * xSize * ySize) + (y * xSize) + x;
}
Run Code Online (Sandbox Code Playgroud)
正如其他人所说,最好分配一个连续的内存块,然后自己弄清楚索引.如果需要,您可以编写一个函数来执行此操作.但是既然你似乎对知道如何处理多个malloc()案例感兴趣,这里有一个例子:
首先,我定义一个函数free_data(),它释放一个int ***with xlen和ylen作为前两个维度大小.我们不需要一个zlen参数,就像free()不释放指针的长度一样.
void free_data(int ***data, size_t xlen, size_t ylen)
{
size_t i, j;
for (i=0; i < xlen; ++i) {
if (data[i] != NULL) {
for (j=0; j < ylen; ++j)
free(data[i][j]);
free(data[i]);
}
}
free(data);
}
Run Code Online (Sandbox Code Playgroud)
该函数遍历指针data,找出i个int **指针data[i].那么,对于一个给定的int **指针,它遍历它,找出j个int *中data[i][j],并释放它.它还需要释放data[i]一旦它释放所有data[i][j],最后,它需要释放data自己.
现在来分配功能.错误检查功能有点复杂.特别是,由于存在1 + xlen + xlen*ylen malloc调用,我们必须能够处理任何这些调用中的失败,并释放到目前为止我们分配的所有内存.为了简化操作,我们依赖于free(NULL)no-op 这一事实,因此我们将所有指针设置在给定级别,等于NULL我们尝试分配它们之前,这样如果发生错误,我们就可以释放所有指针.
除此之外,功能很简单.我们首先为xlen int **值分配空间,然后对于每个xlen指针,我们为ylen int *值分配空间,然后对于每个xlen*ylen指针,我们为zlen int值分配空间,为我们提供xlen*ylen*zlen int值的总空间:
int ***alloc_data(size_t xlen, size_t ylen, size_t zlen)
{
int ***p;
size_t i, j;
if ((p = malloc(xlen * sizeof *p)) == NULL) {
perror("malloc 1");
return NULL;
}
for (i=0; i < xlen; ++i)
p[i] = NULL;
for (i=0; i < xlen; ++i)
if ((p[i] = malloc(ylen * sizeof *p[i])) == NULL) {
perror("malloc 2");
free_data(p, xlen, ylen);
return NULL;
}
for (i=0; i < xlen; ++i)
for (j=0; j < ylen; ++j)
p[i][j] = NULL;
for (i=0; i < xlen; ++i)
for (j=0; j < ylen; ++j)
if ((p[i][j] = malloc(zlen * sizeof *p[i][j])) == NULL) {
perror("malloc 3");
free_data(p, xlen, ylen);
return NULL;
}
return p;
}
Run Code Online (Sandbox Code Playgroud)
请注意,我已经简化了malloc调用:通常,您不应该转换返回值malloc,并将您要分配的对象指定为操作sizeof符而不是其类型.这使得malloc调用编写更简单,更不容易出错.您需要包括stdlib.h的malloc.
这是一个使用以上两个函数的测试程序:
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <time.h>
int main(void)
{
int ***data;
size_t xlen = 10;
size_t ylen = 100;
size_t zlen = 300;
size_t i, j, k;
srand((unsigned int)time(NULL));
if ((data = alloc_data(xlen, ylen, zlen)) == NULL)
return EXIT_FAILURE;
for (i=0; i < xlen; ++i)
for (j=0; j < ylen; ++j)
for (k=0; k < zlen; ++k)
data[i][j][k] = rand();
printf("%d\n", data[1][2][1]);
free_data(data, xlen, ylen);
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
如果您发现它更容易使用,请务必使用此方法.一般来说,这比使用连续的大块内存要慢,但是如果你发现上述方案的速度没问题,并且如果它让你的生活更轻松,你可以继续使用它.即使您不使用它,也很高兴知道如何使这样的方案工作.
你确定需要使用malloc吗?C允许本地创建多维数组:
int a2[57][13][7];
Run Code Online (Sandbox Code Playgroud)
或者您可以通过malloc以下方式使用:
int (*a)[13][7]; // imitates 3d array with unset 3rd dimension
// actually it is a pointer to 2d arrays
a = malloc(57 * sizeof *a); // allocates 57 rows
a[35][7][3] = 12; // accessing element is conventional
free(a); // freeing memory
Run Code Online (Sandbox Code Playgroud)
C89中没有办法做你想做的事情,因为C中的数组类型只能用编译时已知值指定.因此,为了避免疯狂的动态分配,你必须坚持一维方式.您可以使用一个功能来简化此过程
int index(int x, int y, int z) {
return x + (y*xSize) + (z*ySize*xSize);
}
int value = array[index(a, b, c)];
Run Code Online (Sandbox Code Playgroud)
在C99中,即使维度是运行时值,也可以使用普通的数组语法:
int (*array)[X][Y][Z] = (int(*)[X][Y][Z])malloc(sizeof *p);
// fill...
int value = (*array)[a][b][c];
Run Code Online (Sandbox Code Playgroud)
但是,它仅适用于本地非静态数组.
哦,我讨厌malloc数组分配^^
这是一个正确的版本,基本上它只是一个不正确的行:
int main () {
int ***array = (int***)malloc(3*sizeof(int**));
int i, j;
for (i = 0; i < 3; i++) {
// Assign to array[i], not *array[i] (that would dereference an uninitialized pointer)
array[i] = (int**)malloc(3*sizeof(int*));
for (j = 0; j < 3; j++) {
array[i][j] = (int*)malloc(3*sizeof(int));
}
}
array[1][2][1] = 10;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
39436 次 |
| 最近记录: |