我创建了2个结构来表示C中的图像(像素和图像)。
typedef struct pixel {
unsigned char red;
unsigned char green;
unsigned char blue;
};
typedef struct image {
int width;
int heigth;
struct pixel pixels[width][heigth];
};
我收到一条错误,说明图像的定义中没有定义宽度和高度。我不知道为什么我会收到这个错误以及如何解决它
答案 0 :(得分:4)
在C99及更高版本中,您可以在结构的末尾添加(一维)灵活数组成员(FAM):
§6.7.2.1结构和联合说明符
¶18作为一种特殊情况,具有多个命名成员的结构的最后一个元素可以 有一个不完整的数组类型;这称为灵活数组成员。在大多数情况下, 灵活的数组成员被忽略。特别是,结构的大小就像是 省略了灵活的数组成员,除了它可能有更多的尾随填充 遗漏意味着。但是,当
.
(或->
)运算符具有左操作数时 (指向)具有灵活数组成员和右操作数名称的结构 成员,它的行为好像该成员被替换为最长的数组(具有相同的 元素类型)不会使结构大于被访问的对象;该 数组的偏移量应保持灵活阵列成员的偏移量,即使这会有所不同 从替换阵列的。如果此数组没有元素,则表现得好像 它有一个元素,但如果有任何尝试访问它,行为是未定义的 元素或生成一个经过它的指针。
这意味着你可以写:
typedef struct image
{
int width;
int height;
struct pixel pixels[];
} image;
但您必须自己进行2D到1D索引映射。您还必须小心如何分配结构(必要时,它将由malloc()
分配,否则数组的大小将为零。)
注意height
的拼写修正;另请注意为typedef
添加了一个名称(我选择了image
来匹配结构标记,但您可以选择其他任何您喜欢的名称)。没有名称的typedef
是“有效”但没有用 - 您可以省略typedef
并获得相同的结果。
您可以使用:
image *ip = malloc(sizeof(image) + width * height * sizeof(struct pixel));
if (ip != 0)
{
ip->width = width;
ip->height = height;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
ip->pixels[i*width + j] = default_pixel_value;
}
…use ip…
free(ip);
}
我不确定是否有一种将2D阵列作为FAM的好方法。
答案 1 :(得分:3)
您正在使用所谓的可变长度数组,但是,这是一个问题。在C中,每个结构必须具有特定的字节长度,因此,例如,可以评估sizeof(struct image)
。在您的情况下,变量长度数组的大小无法在编译时确定,因此它是非法的。
另一方面,您可能需要指针,而不是声明长度的数组:
typedef struct image
{
int width;
int heigth;
struct pixel **pixels;
};
免责声明:偶尔允许使用结构中的VLA,但如果此扩展更多的是错误而不是功能,则意见问题。请参阅:Undocumented GCC Extension: VLA in struct
编辑:remyabel指出了GCC文档,这些文档讨论了结构中的VLA是否正常的罕见情况:https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html#Variable-Length
答案 2 :(得分:1)
我会建议这样的替代方案:
typedef struct
{
int width;
int heigth;
struct pixel *pixels;
} image;
每次都需要分配:
image img;
/* init */
img.pixels=malloc(sizeof(struct pixel)*img.width*img.height);
*(img.pixels+img.height*i+j)
代表img.pixels[i][j]
。