struct中的变量长度数组

时间:2014-10-03 17:25:22

标签: c arrays struct variable-length-array

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

我收到一条错误,说明图像的定义中没有定义宽度和高度。我不知道为什么我会收到这个错误以及如何解决它

3 个答案:

答案 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]