【问题标题】:Allocating a 2-dimensional structure array with malloc使用 malloc 分配二维结构体数组
【发布时间】:2021-05-13 01:06:07
【问题描述】:

对于我的项目,我需要将 PPM(P3) 图像读入内存。因为我想旋转输入图片,因此我想通过一个 x 和 y 轴/数组。

首先,我将图像的值读入“无符号字符”,因为使用的颜色值仅在 0 到 255 之间,为了节省内存,我将它们转换为无符号字符。

PPM 图像中的每个像素都有一个红色、绿色、蓝色值。

为此,我创建了这个typedef struct

typedef struct{
    unsigned char red;
    unsigned char greed;
    unsigned char blue;
} color;

我试着像这样制作一个简单的二维数组:

color inputColor[pictureHeight][pictureWidth];

但是当图片变大时,这很快就会失败。 我试图让它工作,所以我可以用 malloc 分配那个二维数组。 一种尝试是:

color *inputColor[pictureHeight][pictureWidth];

//Allocating memory
for (int y = 0; y < pictureHeight; y++){
    for (int x = 0; x < pictureWidth; x++){
        inputColor[y][x] = malloc(sizeof(color));
    }
}

// Here i am copying values from an inputStream to the structure
int pixel = 0;
for (int y = 0; y < pictureHeight; y++){
    for (int x = 0; x < pictureWidth; x++){
        inputColor[y][x]->red = inputMalloc[pixel];
        pixel++;
        inputColor[y][x]->green = inputMalloc[pixel];
        pixel++;
        inputColor[y][x]->blue = inputMalloc[pixel];
        pixel++;
    }
}

但它在第一行再次失败......

如何使用malloc 分配二维结构数组,所以图片大小不再那么重要了?

现在它在 700x700 像素左右的图片大小时失败了。

【问题讨论】:

  • color (*inputColor)[pictureWidth] = malloc(pictureHeight * sizeof *inputColor);。与inputColor[y][x].red...一起使用它。
  • 我已经尝试过了,但是我得到了“分段错误(核心转储)”。
  • 假设您有一个符合 C99 的编译器:Correctly allocating multi-dimensional arrays
  • @mch: 回答一下。

标签: arrays c pointers struct malloc


【解决方案1】:

pointer to array approach posted by mch,我认为是最好的方法:

#include <stdlib.h>

color (*inputColor)[pictureWidth] = malloc(pictureHeight * sizeof *inputColor);

访问权限与您使用的相同,inputColor[y] 用于行,inputColor[y][x] 用于列,inputColor[y][x].red 用于访问结构成员。

既然你说你不能让它工作,你可以尝试使用指向指针的方法,虽然速度较慢,但​​可能更容易理解和应用:

color **inputColor;

inputColor = malloc(pictureHeight * sizeof *inputColor);

for (int y = 0; y < pictureHeight; y++)
{
    inputColor[y] = malloc(pictureWidth * sizeof **inputColor);
}

第一个mallocpictureHeight的行数分配内存,for循环为每一行分配内存,大小为pictureWidth

访问与指向数组方法的指针相同。

在这些简化的代码中不执行错误检查,这是您应该做的事情,即检查 malloc 返回值是否有错误。

完成后不要忘记释放内存:

第一个例子:

free(inputColor);

第二个:

for (int y = 0; y < pictureHeight; y++)
{
    free(inputColor[y]);
}
free(inputColor);

【讨论】:

  • 这种方法要糟糕得多,除非您希望能够在 O(1) 时间内“交换行”。它使用更多内存,更多碎片内存(占用更多缓存行)并且访问效率较低(双指针取消引用而不是单指针)。您真的应该使用 mch 评论中的方法,这应该是一个答案。
  • @R..GitHubSTOPHELPINGICE 虽然我同意指向数组方法的指针更好,但事实仍然是 OP 似乎无法使其工作,因此我的替代答案。与往常一样,可以对其进行改进的功能代码比不工作的代码要好。
  • @anastaciu 这是为图像或屏幕缓冲区分配缓冲区的一种非常糟糕的方法。最低效的方式。
  • @0___________ 这可以说是一个坏方法;这不是“非常糟糕”。虽然它可能效率较低,但它并不是“最低效的”。指针对指针的技术已经使用了很多年,被知道自己在做什么的人使用,并取得了完美的结果。
  • @0___________ 这不是最好的方法,我同意,我在回答中说了这么多,它仍然是一种有效的方法。
【解决方案2】:

只需分配一个双指针并为其分配内存:

color **inputColor;

inputcolor= malloc(sizeof(color*)*pictureHeight);
for (int y = 0; y < pictureHeight; y++){
        inputColor[y] = malloc(sizeof(color)*pictureWidth);
   
}

【讨论】:

  • 谢谢!这完美地解决了我的问题:D
  • 正确,我是想写颜色*
  • 每当您看到循环的malloc() 调用时,您都没有分配到二维数组。您将一维指针数组分配给多个完全独立的一维数组。而当尺寸变大时,那就是 slow
  • @AndrewHenle 代码的性能更多地取决于分配数据的使用方式,而不是分配方式。为了获得良好的性能评估,我们需要更大的应用程序。
  • @chux-ReinstateMonica 使用malloc() 在最终维度类似于[512][512][512][512] 的嵌套循环中分配int **** 的时间。那应该是 256GB,具有足够内存的系统越来越普遍。现在是时候分配一个真正的四维数组了,需要调用一次malloc()。你甚至可以在后者中包含memset()...当你进入更大的指针到指针到指针的“假数组”时,这些分配会变得很重要。当然,优化它们几乎是微不足道的。
【解决方案3】:

双指针解决方案在考虑图像时有一个非常薄弱的​​地方。它们不能直接传输到屏幕内存或快速访问。

更好的是使用指向数组的指针。

typedef struct{
    unsigned char red;
    unsigned char greed;
    unsigned char blue;
} color;

int main(void)
{

    size_t pictureHeight = 600, pictureWidth = 800;

    color (*inputColor)[pictureHeight][pictureWidth];

    inputColor = malloc(sizeof(*inputColor));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-29
    • 2021-03-05
    • 2019-06-07
    • 2012-08-10
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    相关资源
    最近更新 更多