我必须使用三维数组,因为我想将图片划分为正方形,并将每个正方形的RGB平均值存储在我的数组中。我希望它是这个尺寸,tab[height][width][3]
,所以我做了:
i = 0; j = 0; k = 0;
float*** tab;
tab = malloc((hauteur+1)*sizeof(float*));
while(i <= hauteur){
tab[i] = malloc((largeur+1)*sizeof(float**) );
i++;
}
i = 0;
while(i <= hauteur){
j = 0;
while (j <= largeur){
tab[i][j] = malloc(3*sizeof(float***));
j++;
}
i++;
}
但是我在tab[1][30][2];
之后有一个segfault。
我的malloc
有问题吗?
这很奇怪,因为当我使用以下语句声明tab
时,它不会出错:tab[hauteur][largeur][3]
。
(对不起:"hauteur"在法语中的意思是"高度","largur"的意思是指"宽度"。)
(如果你认为你需要检查我的整个功能:http://pastebin.com/eqQXz8Ad;它是JPEG文件的编写器。)
您的类型在malloc
调用中不正确。我建议如下:
tab = malloc( (hauteur + 1) * sizeof *tab ); // sizeof (float **)
tab[i] = malloc( (largeur + 1) * sizeof *tab[i] ); // sizeof (float *)
tab[i][j] = malloc( 3 * sizeof *tab[i][j] ); // sizeof (float)
给定tab
的声明,以下都为真:
Expression Type
---------- ----
tab float ***
*tab float **
tab[i] float **
*tab[i] float *
tab[i][j] float *
*tab[i][j] float
我通常建议使用目标表达式的sizeof
,而不是显式类型;这样,如果您更改tab
的类型(例如,从float
更改为double
),则永远不必触摸malloc
调用。
您正在制作的基本上是一个浮点指针数组数组,而不是一个三维浮点数组。你可能想看看C中二维数组声明中的歧义。它解决了二维数组的类似问题。
也许你的问题的解决方案看起来像:
float (*tab)[hauteur][largeur][3]; //declare a pointer to a real array
tab = malloc(hauteur * largeur * 3 * sizeof(float)); //Allocate room for threedimensional array
for (int i=0; i<hauteur; i++)
for (int j=0; j<largeur; j++)
for (int k=0; k<3; k++)
{
(*tab)[i][j][k] = (float)((i*100)+j*1000+k); //Fill elements with something using threedimensional subscripting
}
for (int i=0; i<hauteur; i++)
for (int j=0; j<largeur; j++)
for (int k=0; k<3; k++)
{
printf("[%d][%d][%d]=%fn", i, j, k, (*tab)[i][j][k]); //Check back data...
}
已编辑通过查看注释,我发现使用指向数组的指针表示法(*array)[a][b]...[n]
访问数组在某种程度上是"不自然的",即使该表示法在声明中显式报告了整个维度。为了使使用更加友好,你可以使用下面的表格,它允许众所周知的格式:
#include <stdio.h>
#include <stdlib.h>
int largeur = 10;
int hauteur = 10;
int main(int argc, char *argv[])
{
float (*tab)[largeur][3]; //declare a bidimensional array of pointers to our variable
//this fools the compiler acting as a one more dimension array of variable
tab = malloc(hauteur * largeur * 3 * sizeof(float)); //Allocate room for threedimensional array
for (int i=0; i<hauteur; i++)
for (int j=0; j<largeur; j++)
for (int k=0; k<3; k++)
{
tab[i][j][k] = (float)((i*100)+j*1000+k); //Fill elements with something using threedimensional subscripting
//This use the natural addressing...
}
for (int i=0; i<hauteur; i++)
for (int j=0; j<largeur; j++)
for (int k=0; k<3; k++)
{
printf("[%d][%d][%d]=%fn", i, j, k, tab[i][j][k]); //Check back data...
}
}
这种技巧之所以有效,是因为C语言中缺乏多维数组概念
C只知道数组,或者更好的是,它应该是某个东西的string,所以二维数组只是某个东西数组的数组。如果我们再加一个维度,它就是一个数组的数组。。。对于我们增加的每一个维度,以此类推
这定义了C中数组的内存布局以及编译器用于访问数据的寻址方法。因为数据在内存中进行流式传输以访问特定下标的值,所以编译器需要计算除第一个维度外的所有维度所使用的空间。
+++我修复了一个错误,现在这个样本可以在任何符合C99-C11的编译器下编译,并且可以工作。
如果你非常关心效率,你应该考虑使用单个维度数组(就像Frankie_C的答案一样):
int height = something_to_compute_height();
int width = something_to_compute_width();
double *arr = malloc(height*width*3*sizeof(double));
if (!arr) { perror("malloc"); exit(EXIT_FAILURE); }
(顺便说一句,即使我们都是母语为法语的人,让我们试着在这里的问题和代码中使用英语)
那么您可以定义一个宏来简化arr
中的某些元素
#define ELEM_ARR(a,i,j,k) a[i*width*height+j*width+k]
#define ARR(i,j,k) ELEM_ARR(arr)
(你已经有了想法,细节可能会有所不同)
这可能比指针数组到指针数组更高效,因为缓存的位置性以及只需要一个单独的分配。
仔细选择行主访问或列主访问,以适应最频繁的访问模式。
如果CCD_ 15&width
特定于每个数组,您可以使用一些灵活的数组成员作为struct
中的最后一个。
根据经验,在C中,只有当所有维度(可能除了最后一个维度)都是编译时常数时,才使用多维数组是有用的,例如double arr3d[3][4][5];
;否则,最好有一个一维数组,自己计算索引。
顺便说一句,如果你非常关心性能,你可能会关心OpenCL和OpenMP(两者通常都喜欢一维数组)。