因此,C99 祝福了常用的“灵活数组成员”hack,允许我们制作struct
可以过度分配的 s 以满足我们的大小要求。我怀疑在大多数理智的实现中这样做是完全安全的,但是如果我们知道在某些情况下我们不需要 a 的某些成员,那么在 C 中“分配不足”是否合法struct
?
抽象例子
假设我有一个类型:
struct a {
bool data_is_x;
void * data;
size_t pos;
};
如果data_is_x
,那么 的类型data
是需要使用pos
成员的类型。否则,使用 this 的函数将struct
不需要. 本质上,携带有关它是否有成员的信息,并且此信息在 的生命周期内不会更改(在邪恶的恶作剧之外,无论如何都会破坏任何东西)。可以安全地说:pos
struct
struct
pos
struct
struct a *a = malloc(data_is_x ? sizeof(struct a) : offsetof(struct a, pos));
pos
只有在需要时才会为成员分配空间?或者它是否违反了使用对于指针来说太小的强制转换空间的约束struct
,即使您从未使用过有问题的成员?
具体例子
我的实际用例有点涉及;它主要在这里,所以您可以理解我为什么要这样做:
typedef struct {
size_t size;
void * data;
size_t pos;
} mylist;
for 的代码mylist_create
指定 forsize > 0
是data
一个连续数据数组,它是size
项长(无论项可能是什么),但size == 0
它是包含项的双向链表的当前节点。与 s 一起工作的所有功能mylist
都会检查size == 0
. 如果是这样,他们会将数据作为链表处理,其中“当前”索引是节点data
指向的任何一个。如果没有,他们会将数据作为数组处理,其中“当前”索引存储在pos
.
现在,如果size == 0
我们真的不需要该pos
成员,但如果size > 0
我们需要的话。所以我的问题是,这样做是否合法:
mylist *list = malloc(size ? sizeof(mylist) : offsetof(mylist, pos));
如果我们保证(对未定义行为的惩罚), while size == 0
,我们将永远不会尝试(或需要)访问该pos
成员?或者它是否在标准中的某个地方说它是 UB 甚至考虑这样做?