【问题标题】:Coding problem using a 2-d array of structs inside another struct in C使用 C 中另一个结构内的二维结构数组的编码问题
【发布时间】:2010-12-25 13:59:38
【问题描述】:

我正在处理一个二维结构数组,它是另一个结构的一部分。这不是我经常做的事情,所以我遇到了问题。这个函数在接近末尾的“测试”for循环后最终失败。它会在出现故障之前正确打印出一行。

将数据读入虚拟二维结构数组的代码部分工作得很好,所以它必须是我的分配数组才能成为另一个结构(imageStruct)的一部分。

任何帮助将不胜感激!

/*the structure of each pixel*/
typedef struct
{
 int R,G,B;
}pixelStruct;

/*data for each image*/
typedef struct
{ 
 int height;
 int width;
 pixelStruct *arr; /*pointer to 2-d array of  pixels*/
} imageStruct;


imageStruct ReadImage(char * filename)
{
 FILE *image=fopen(filename,"r");
 imageStruct thisImage;

        /*get header data from image*/

        /*make a 2-d array of of pixels*/
 pixelStruct imageArr[thisImage.height][thisImage.width];

        /*Read in the image. */

        /*I know this works because I after storing the image data in the
          imageArr array, I printed each element from the array to the
          screen.*/

 /*so now I want to take the array called imageArr and put it in the
   imageStruct called thisImage*/

  thisImage.arr = malloc(sizeof(imageArr));
  //allocate enough space in struct for the image array. 

 *thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*/

//test to see if assignment worked: (this is where it fails)

 for (i = 0; i < thisImage.height; i++)
 {
  for (j = 0; j < thisImage.width; j++)
  {
   printf("\n%d: R: %d G: %d B: %d\n", i ,thisImage.arr[i][j].R,
          thisImage.arr[i][j].G, thisImage.arr[i][j].B);
  }
 } 

 return thisImage;
}

(如果您想知道我为什么首先使用虚拟数组,那是因为当我开始编写这段代码时,我不知道如何去做我现在想做的事情。)

编辑:有人建议我没有在 imageStruct 的 typedef 中正确初始化二维数组。如果确实是问题,谁能帮我纠正这个问题?

【问题讨论】:

  • 顺便说一句:如果您正在使用像素,您可能需要考虑使用平面线性缓冲区,然后使用缓冲区 [y*width + x] 索引点 (x,y)。这很常见,如果您必须将该缓冲区传递给可能采用这种格式的其他人的代码,这可能会有所帮助。
  • 感谢您的建议!我会考虑的。然后我就可以忘记二维数组的混乱了!
  • 我得出的结论是,尝试将二维数组作为结构的一部分是没有希望的。我已经切换到一维数组,现在一切正常。感谢所有帮助过我的人,这是迄今为止我遇到的最有帮助的编程论坛!

标签: c arrays struct


【解决方案1】:

您似乎能够创建可变长度数组,因此您使用的是 C99 系统或支持它的系统。但并非所有编译器都支持这些。如果你想使用它们,你不需要在你的结构中声明 arr 指针。假设没有可变长度数组,让我们看看代码的相关部分:

/*data for each image*/
typedef struct
{ 
    int height;
    int width;
    pixelStruct *arr; /*pointer to 2-d array of  pixels*/
} imageStruct;

arr 是指向pixelStruct 的指针,而不是指向二维像素数组的指针。当然,您可以使用arr 来访问这样的数组,但是该注释具有误导性,并且暗示了一种误解。如果你真的想声明这样一个变量,你可以这样做:

pixelStruct (*arr)[2][3];

和 arr 将是指向“pixelStruct 数组 3 的数组 2”的指针,这意味着 arr 指向二维数组。这不是你真正想要的。公平地说,这不是你声明的,所以一切都很好。但是您的评论表明对 C 中的指针存在误解,这在您的代码中稍后会体现出来。

此时,您最好阅读一篇关于 C 中的数组和指针的精彩介绍,而 Chris Torek 的 C For Smarties: Arrays and Pointers 是一本非常不错的介绍。特别是,请确保您理解页面上的第一个图表以及函数f 定义中的所有内容。

由于您希望能够使用“列”和“行”索引以自然的方式索引arr,我建议您将arr 声明为指向指针的指针。所以你的结构变成了:

/* data for each image */
typedef struct
{ 
    int height;
    int width;
    pixelStruct **arr; /* Image data of height*width dimensions */
} imageStruct;

然后在您的ReadImage 函数中,分配您需要的内存:

int i;
thisImage.arr = malloc(thisImage.height * sizeof *thisImage.arr);
for (i=0; i < thisImage.height; ++i)
    thisImage.arr[i] = malloc(thisImage.width * sizeof *thisImage.arr[i]);

请注意,为清楚起见,我没有对malloc 进行任何错误检查。在实践中,您应该检查malloc是否返回NULL并采取适当的措施。

假设所有内存分配成功,您现在可以读取thisImage.arr 中的图像(就像您在原始函数中为imageArr 所做的那样)。

使用完thisImage.arr 后,请务必释放它:

for (i=0; i < thisImage.height; ++i)
    free(thisImage.arr[i]);

free(thisImage.arr);

在实践中,您需要将上述分配和释放部分包装在它们各自分配和释放arr 对象的函数中,并注意错误检查。

【讨论】:

  • 哇,感谢您提供如此深入的回答!你说的对,我对 C 指针的理解很差。我想我的问题现在已经完全解决了。再次感谢!
【解决方案2】:

我认为sizeof imageArr 在您使用运行时大小的数组时不会像您期望的那样工作。顺便说一句,这是一种“利基”C99 功能。您应该添加一些关键值的打印输出,例如 sizeof 以查看它是否符合您的想法。

更清楚的是使用数组的显式分配:

thisImage.arr = malloc(thisImage.width * thisImage.height * sizeof *thisImage.arr);

我也认为很难(如果可能的话)像这样实现一个“真正的”二维数组。我建议您自己进行地址计算,即访问这样的像素:

unsigned int x = 3, y = 1; // Assume image is larger.
print("pixel at (%d,%d) is r=%d g=%d b=%d\n", x, y, thisImage.arr[y * thisImage.width + x]);

我看不到在运行时如何将所需的维度信息与数组关联;我认为这是不可能的。

【讨论】:

  • 如果 height=10 和 width=1,并且矩阵上的每个点都有 3 个用于 pixelStruct 结构的整数,那么每个槽应该是 3*4 = 12 个字节,所以对于整个矩阵,它是 120 ... 我对么?如果是这样,那么我的代码“sizeof imageArr”可以正常工作。我尝试了您的代码,但 sizeof *thisImage.arr 为 4。当我用您的代码替换我的 malloc 代码时,我得到了完全相同的结果。感谢您迄今为止的帮助!
  • 如果 sizeof *thisImage.arr 是四,那么您显示的代码有问题。它应该是指向数据的大小,即 sizeof (pixelStruct)。你把星星加进去了吗?
  • 是的,你是对的。我已将声明从 pixelstruct *arr 更改为 pixelstruct **arr。所以现在结果是 12 和 120,但这与我原来的 malloc 的结果相同。谢谢。
  • 我想这是我的问题。它只是不能作为二维数组工作。感谢您的输入!我正在切换到一维。
【解决方案3】:

高度和宽度未定义;您可能想先初始化它们,如

thisImage.height = 10; thisImage.width = 20;

还有,

  • 什么是 colorRGB?

【讨论】:

  • 高度和宽度是我在“获取图像的标题数据”部分中取出的代码部分中定义的。这些值没有问题。 ColorRGB 是我的 pixelStruct 结构的原始名称。我做了一个查找和替换来更改它,但我错过了一个。谢谢
【解决方案4】:

*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*

这行不通。您必须将 arr 声明为 colorRGB **,并相应地分配它,等等。

【讨论】:

    【解决方案5】:

    看起来您正在尝试通过赋值复制数组。 您不能使用简单的赋值运算符来执行此操作,您必须使用一些函数来复制内容,例如 memcpy。

    *thisImage.arr = *imageArr;
    thisimage.arr[0] = imagearr[0];
    

    上面的语句做同样的事情。 但是,这不太可能是导致内存损坏的原因

    由于您使用的是二维数组,因此请确保正确初始化它们。 查看代码,甚至不应该编译:数组在您的图像结构中声明为一维但您将其称为二维?

    【讨论】:

    • 如何在图像结构中将数组声明为二维?谢谢。
    猜你喜欢
    • 2014-01-25
    • 2021-09-22
    • 1970-01-01
    • 2018-12-29
    • 2021-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多