当我在结构中有一个数组时,我的意思是完全清楚的:当定义结构时,保留整个数组的内存,当我复制结构时,所有数组内容都被复制。
typedef struct {
uint8_t type;
struct {
uint8_t length;
uint8_t data[5];
} m;
} s;
但是当我使用uint8_t data[]
时,这是什么意思?我猜这可能与uint8_t *data
相同,但事实并非如此。当我尝试像这样分配它时:
s the_s;
uint8_t something[] = {1, 2, 3};
the_s.m.data = something;
编译器给我
无法分配数组类型对象
答案 0 :(得分:3)
作为结构的最后一个成员的不完整类型的数组是名为灵活数组成员功能的C99功能。
在本声明中
the_s.m.data = something;
您正在尝试分配数组,但在C中,无法分配数组。
答案 1 :(得分:2)
您假设data[]
与*data
相同,这是不正确的。
当动态分配以数组结尾的结构时,可以使用未指定的数组长度,但它绝不意味着您获得可分配的指针。
答案 2 :(得分:2)
不完整的数组类型是对已分配数组的第一项的位置的引用,但实际上并未为该项分配空间。在一些较旧的C编译器中,可以通过声明一个大小为零的数组来获得类似的效果,尽管这样做在C标准的任何“官方”版本中都不合法。此类声明的主要用途是使用malloc,calloc或其他类似机制分配的结构;为struct分配空间的代码将分配足够的额外空间来处理所需数量的数组项。
在C中不完整的数组声明变得合法之前,常见的解决方法是声明一个大小为1的数组,然后从要附加到结构的元素数中减去一个。例如:
struct { int this,that,whatever; char name[1]; } MYSTRUCT; void test(char *new_name, int new_name_length) { MYSTRUCT *ms = malloc(sizeof(MYSTRUCT)+new_name_length-1); memcpy(ms->name, new_name, new_name_length); }
然而,这种方法有几个方面:
如果C编译器根本没有包含拒绝零大小数组的代码,并且标准规定任何数组的最大下标值是(unsigned int)(size-1),那么struct hack会更清晰。不幸的是,标准不是那样写的。