使用C中另一个结构内的二维结构数组编码问题

我正在使用二维结构数组,这是另一个结构的一部分。 这不是我已经做了很多事情所以我遇到了问题。 在接近结束的“测试”for-loop之后,此函数最终失败。 它在出现故障之前正确打印出一行。

我的代码中将数据读入虚拟2-d结构数组的部分工作得很好,因此它必须是我的赋值数组才能成为另一个结构(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中正确初始化我的二维数组。 如果问题确实存在,任何人都可以帮我纠正吗?

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

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

arr是指向pixelStruct的指针,而不是指向pixelStruct数组。 当然,你可以使用arr来访问这样一个数组,但这个注释是误导性的,它暗示了一个误解。 如果你真的想声明这样一个变量,你会做类似的事情:

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

arr将是指向“pixelStruct的数组3的数组2”的指针,这意味着arr指向2-d数组。 这不是你想要的。 公平地说,这不是你宣布的,所以一切都很好。 但是你的评论暗示了对C中指针的误解,这在你的代码中会有所体现。

在这一点上,你将很好地阅读C中的数组和指针的一个很好的介绍,一个非常好的是C For Smarties:arrays和指针 Chris Torek。 特别是,请确保您了解页面上的第一个图表以及函数f定义中的所有内容。

由于您希望能够使用“column”和“row”索引以自然方式索引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对象的各自函数中,并负责错误检查。

我不认为当你使用运行时大小的数组时, sizeof imageArr效果与你期望的一样。 哪个,顺便说一句,是一种“利基”C99function。 您应该添加一些关键值的打印输出,例如sizeof以查看它是否符合您的想法。

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

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

我也认为实现像这样的“真正的”2Darrays很困难(如果可能的话)。 我建议你自己做地址计算,即访问像这样的像素:

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

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

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

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

也,

  • 什么是colorRGB?

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

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

它看起来像你试图通过赋值复制数组。 您不能使用简单赋值运算符来执行此操作,您必须使用某些函数来复制内容,例如memcpy。

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

上述陈述也在做同样的事情。 然而,这不太可能是导致内存损坏的原因

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