使用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];
上述陈述也在做同样的事情。 然而,这不太可能是导致内存损坏的原因
由于您正在使用二维数组,请确保正确初始化它们。 看代码,甚至不应该编译:数组在你的图像结构中声明为一维,但你称为二维?