c-对三维数组进行Mallocing



我必须使用三维数组,因为我想将图片划分为正方形,并将每个正方形的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(两者通常都喜欢一维数组)。

相关内容

  • 没有找到相关文章

最新更新