【问题标题】:Dynamically Allocating a 2D Matrix of Structs in C在 C 中动态分配结构的二维矩阵
【发布时间】:2020-10-16 04:42:47
【问题描述】:

我正在用 C 语言编写一个程序,它将读取位图格式的图像,并调整一些图像参数,如颜色、使图像灰度等。我已经加载了图像,并将图像标题存储在 2结构遵循 Microsoft 的文档,here。我在为 2D 数组动态分配内存时遇到问题,该数组将用作要写出的新图像。矩阵中的每个索引都是一个 RGB 结构 PX_RGB

typedef struct RGB {
    BYTE rgbPK_BLUE;
    BYTE rgbPK_GREEN;
    BYTE rgbPK_RED;
} PX_RGB;

我已经阅读了许多主题,其中最有帮助的是: Calloc a Two-Dimensional Array,而这个帮助不大: I have problems making a function to handle a matrix using calloc。 (BYTE 只是 uint8_t 的别名)。如果我天真地仅根据输入图像中的字节数和structs 的大小进行分配:

PX_RGB *new_image = calloc(img_information.bi_size_image, sizeof(PX_RGB));

我无法像矩阵一样索引它(即new_image[i][j] = ... 第一个线程的 cmets 和响应似乎表明将一个图像尺寸放在左侧并以这种方式分配:

PX_RGB (*new_image)[image_width] = calloc(image_height, image_width * sizeof(PX_RGB));

但是编译器对此并不满意,因为任何潜在图像的大小在编译时都是未知的。还有一个不同的解决方案,但这似乎没有做任何事情 - 检查NULL 也没有尝试索引它的代码似乎做任何事情:

PX_RGB **new_image;
new_image = calloc(image_height, image_width * sizeof(new_image));

if (new_image == NULL) { printf("\nError: Could not allocate image memory.\n"); return -1; }
for (int i = 0; i < image_height; i++)
{
    for (int j = 0; j < image_width; j++)
    {
        new_image[i][j].rgbPK_BLUE = j;
        printf("\nIndex [%d][%d] = %d", i, j, new_image[i][j].rgbPK_BLUE);
    }
}

我已经在第一个线程中看到这被用作答案,但是在 ([3]) 中需要的列数是已知的并且是硬编码的。 我遇到了这个公式来获得正确的行偏移here,我认为这个测试代码似乎可以正常工作:

PX_RGB *new_image = calloc(image_height, image_width * sizeof(new_image));

int offset = 0;

for (int i = 0; i < image_height; i++)
{
    for (int j = 0; j < image_width; j++)
    {
        offset = (j * image_width) + i;
        new_image[offset].rgbPK_BLUE = j;
        printf("\nIndex [%d][%d] = %d", i, j, new_image[offset].rgbPK_BLUE);
    }
}

那么,有没有办法按照我想要的方式索引动态分配的内存?理想情况下,我想将我的新图像传递给这样的操作函数:

void grayscale(int image_height, int image_width, PX_RGB new_image[image_height][image_width])
{
    return;
}

因为我已经看到其他代码这样做了,我很困惑为什么我不能让我的版本工作,以及我做错了什么。我应该说我从哈佛在 edX 上关于计算机科学的公开讲座系列中得到了这个项目的想法,他们似乎以我想要的方式实现了这个逻辑。非常感谢您的帮助,干杯!

【问题讨论】:

  • "编译器对此不满意,因为在编译时不知道任何潜在图像的大小" --> 一种出路,使用支持 VLA 的 C99 编译器或更高版本.
  • @chux-ReinstateMonica 感谢您的回复 - 我在另一个线程中看到了这一点。我用gcc -v检查了我的编译器版本,我在mingw-w64 8.1.0,在Windows上。我记得至少在过去 6 个月内下载过这个。我需要传递任何编译器标志来指定 C 版本吗?
  • GCC 8 默认为 C11 一致性 + 扩展,包括对可选(在 C11 中)VLA 功能的支持。它应该接受PX_RGB (*new_image)[image_width] 变体,前提是image_width 作为整数变量的声明在范围内,并且该变量已被分配一个正值。这是可用的最干净的选项之一,因此,如果它不适合您,那么请详细说明您正在尝试的具体内容以及 GCC 对此的看法。

标签: c gcc memory


【解决方案1】:

您可以通过以下小技巧将其作为矩阵访问:

new_image[i][j] == *(new_image + (i*num_of_columns) + j);

因为二维数组只不过是一个具有连续内存分配的线性数组。 或者,您可以将其类型转换为

typedef Px_RGB (*ptype)[no_of_columns];
ptype new_image_indexed = (ptype)new_image;

现在 new_image_indexed 可以访问为

new_image_indexed[i][j];

【讨论】:

  • 感谢您的回复,我想我在原始帖子的某处提到了您提到的第一种逐行索引方法。不过,您的 typedef 想法非常简洁,我可能会将其用作备份所有其他方法都失败了。
猜你喜欢
  • 2021-03-03
  • 1970-01-01
  • 2011-12-02
  • 2018-07-10
  • 1970-01-01
  • 2023-03-06
  • 2016-08-13
  • 2014-11-24
  • 1970-01-01
相关资源
最近更新 更多