【发布时间】:2011-09-09 02:02:03
【问题描述】:
因此,C99 祝福了常用的“灵活数组成员”hack,使我们能够创建 structs,它可以被过度分配以满足我们的大小要求。我怀疑在大多数理智的实现中这样做是完全安全的,但是如果我们知道在某些情况下我们不需要 struct 的某些成员,那么在 C 中“分配不足”是否合法?
抽象例子
假设我有一个类型:
struct a {
bool data_is_x;
void * data;
size_t pos;
};
如果data_is_x,那么data的类型就是需要使用pos成员的类型。否则,使用此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;
mylist_create 的代码指定,对于 size > 0,data 是一个连续数据数组,长度为 size 个项目(无论项目是什么),但对于 size == 0,它是包含项目的双向链表的当前节点。所有与mylists 配合使用的函数都会检查size == 0 是否存在。如果是这样,他们会将数据作为链表处理,“当前”索引是data 指向的任何节点。如果没有,他们会将数据作为数组处理,“当前”索引存储在pos 中。
现在,如果size == 0 我们真的不需要pos 成员,但如果size > 0 我们需要。所以我的问题是,这样做是否合法:
mylist *list = malloc(size ? sizeof(mylist) : offsetof(mylist, pos));
如果我们保证(对未定义行为的惩罚),虽然size == 0,我们永远不会尝试(或需要)访问pos 成员?或者它是否在标准中的某个地方说它是 UB 甚至考虑这样做?
【问题讨论】:
-
这是一个非常好的问题,我很遗憾地说我不知道答案。我希望你给出一个更简单的例子;我有一种感觉,人们很难追随...无论如何+1。
-
@R.. - 这基本上是我的用例;我使用它是因为我认为一个更抽象的例子可能没有意义,并提出了“你为什么要这样做?”的问题。 (当我看到人们试图做一些不明智的事情时,我自己经常会问这个问题)。如果您认为它会使问题更清楚,我可以将其更改为更简单,或者我可以保留它并添加一个更简单的版本。
-
我会留下它,但更简单的版本可能也不错。
标签: c malloc flexible-array-member