7

我创建了 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];
    };

我收到一条错误消息,说图像定义中未定义宽度和高度。我不明白为什么会出现该错误以及如何解决它

4

3 回答 3

9

在 C99 及更高版本中,您可以在结构的末尾有一个(一维)灵活数组成员(FAM):

§6.7.2.1 结构和联合说明符

¶18 作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型;这称为灵活数组成员。在大多数情况下,灵活数组成员被忽略。特别是,结构的大小就像省略了柔性数组成员一样,只是它可能具有比省略所暗示的更多的尾随填充。然而,当一个.(或->) 运算符的左操作数是(指向)具有灵活数组成员的结构,右操作数命名该成员,它的行为就好像该成员被替换为最长的数组(具有相同的元素类型),不会使结构大于被访问的对象;数组的偏移量应保持灵活数组成员的偏移量,即使这与替换数组的偏移量不同。如果这个数组没有元素,它的行为就好像它有一个元素,但如果尝试访问该元素或生成一个越过它的指针,则行为是不确定的。

这意味着你可以写:

typedef struct image
{
    int width;
    int height;
    struct pixel pixels[];
} image;

但是您必须自己进行 2D 到 1D 索引映射。您还必须小心如何分配结构(必要时,它将被分配,malloc()否则数组的大小将为零)。

注意height;的拼写修正 还要注意添加的名称typedef(我选择image匹配结构标签,但您可以选择您喜欢的任何其他名称)。没有名字的Atypedef是“有效的”但没有用——你可以省略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);
}

我不确定是否有一种将二维数组作为 FAM 的好方法。

于 2014-10-03T17:43:56.457 回答
3

您正在使用所谓的变长数组,但是,有一个问题。在 C 中,每个结构都必须具有特定的字节长度,以便例如sizeof(struct image)可以评估。在您的情况下,可变长度数组的大小无法在编译时确定,因此它是非法的。

另一方面,您可能需要那里的指针,而不是声明长度的数组:

typedef struct image
{
    int width;
    int heigth;
    struct pixel **pixels;
};

免责声明:结构中的 VLA 偶尔是允许的,但如果此扩展更多的是错误而不是功能,这是一个意见问题。请参阅:未记录的 GCC 扩展:结构中的 VLA

编辑:remyabel 指出 GCC 文档讨论了结构中的 VLA 可以正常使用的罕见情况: https ://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html#Variable-Length

于 2014-10-03T17:33:39.217 回答
2

我会建议这样的替代方案:

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]

于 2014-10-03T17:34:39.773 回答