C 结构中的可变长度数组

C 结构中的可变长度数组,c,arrays,struct,variable-length-array,C,Arrays,Struct,Variable Length Array,我已经创建了两个结构来用C表示图像(一个像素和一个图像) 我得到一个错误,说宽度和高度没有定义在图像的定义。我不明白为什么会出现这样的错误,以及如何解决它您使用的是所谓的可变长度数组,但是,有一个问题。在C语言中,每个结构必须有一个特定的字节长度,这样,例如,sizeof(struct image)就可以被计算。在您的例子中,可变长度数组的大小不能在编译时确定,因此它是非法的 另一方面,您可能需要指针,而不是声明长度的数组: typedef struct image { int widt

我已经创建了两个结构来用C表示图像(一个像素和一个图像)


我得到一个错误,说宽度和高度没有定义在图像的定义。我不明白为什么会出现这样的错误,以及如何解决它

您使用的是所谓的可变长度数组,但是,有一个问题。在C语言中,每个结构必须有一个特定的字节长度,这样,例如,
sizeof(struct image)
就可以被计算。在您的例子中,可变长度数组的大小不能在编译时确定,因此它是非法的

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

typedef struct image
{
    int width;
    int heigth;
    struct pixel **pixels;
};
免责声明:结构中的VLA偶尔是允许的,尽管如果这个扩展更像是一个bug而不是一个特性,这是一个意见问题。见:


编辑:remyabel指出了GCC文档中关于结构中VLA正常的罕见情况:

我建议这样一种替代方案:

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)
表示C99及更高版本中的
img.pixels[i][j]
,您可以在结构的末端有一个(一维)灵活数组成员(FAM):

§6.7.2.1结构和联合规范 作为一种特殊情况,具有多个命名成员的结构的最后一个元素可以 具有不完整的数组类型;这称为灵活数组成员。在大多数情况下, 将忽略灵活数组成员。特别是,结构的大小就像 省略了flexible数组成员,只是它的尾部填充可能比 这一遗漏意味着。但是,当
(或
->
)运算符的左操作数为 (指向)具有灵活数组成员和正确操作数名称的结构 成员,其行为就好像该成员被替换为最长的数组(具有相同的 元素类型),不会使结构大于正在访问的对象;这个 阵列的偏移量应保持柔性阵列构件的偏移量,即使这会有所不同 从替换阵列的。如果这个数组没有元素,它的行为就像 它只有一个元素,但如果试图访问该元素,则行为未定义 元素或来生成一个指针,该指针超过它一个

这意味着你可以写:

typedef struct image
{
    int width;
    int height;
    struct pixel pixels[];
} image;
但是您必须自己进行2D到1D索引映射。您还必须注意如何分配结构(当然,它将由
malloc()
分配,否则数组的大小将为零)

注意
高度的拼写修正
;还要注意为
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);
}
image*ip=malloc(sizeof(image)+宽度*高度*sizeof(struct pixel));
如果(ip!=0)
{
ip->宽度=宽度;
ip->高度=高度;
对于(int i=0;ipixels[i*width+j]=默认的像素值;
}
…使用ip…
免费(ip);
}

我不确定是否有一个好方法可以获得FAM的2D数组。

C99不允许VLA出现在结构中。原因很简单:如果struct的字段是VLA,我如何确定这个struct有多大?是的,C需要在编译时知道数组的大小。C中的图像通常用一个指针来表示,一旦高度和宽度已知,数据就会被错误定位。我相信他们现在已经在structs中为VLAs添加了文档。
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);
}