C?中具有多个灵活阵列成员的情况

  • 本文关键字:阵列 成员 情况 c
  • 更新时间 :
  • 英文 :


问题:我通过网络接收动态大小的结构并将其存储在磁盘上。现在我想提供一些函数来处理这个连续内存块。

示例:以下当然不起作用,它只是一个示例:

typedef struct person {
size_t name_size;
const char name[];
} person;
typedef struct group {
size_t caption_size;
const char caption[];
size_t group_size;
person people[];
} group;
person *group_get_people(const group *g);
const char *person_get_name(const person *p);
size_t person_get_name_size(const person *p);
...

要求:API应该有类型,所以很清楚要传递什么,如果传递了错误的类型,编译器应该发出警告。

我所尝试的:我目前正在考虑typedef person void;,并且只是计算实现中的偏移量。然而,如果传递了错误的类型,编译器不会发出警告。

问题:如何表示这样的数据结构?最常见的方法是什么?

您不能在C中用类型安全表示条件内存布局,但您可以将类型安全的指针包装器提供为结构,并将指针作为单个成员。类似的东西:

typedef struct group_ptr {
void* p;
} group_ptr;
typedef struct person_ptr {
void* p;
} person_ptr;
person_ptr group_get_person(group_ptr g, size_t i);

不幸的是,除了添加更多像const_group_ptrconst_person_ptr这样的类之外,我看不到处理constness的简单方法。

我会提出这样的建议(这是伪代码,因为您没有提供太多(,但这是主要思想。基本上,您有"经典"结构group和person,它们可以被分配并与标准指针链接(如注释中所述(,并且您有用于读取序列化数据的flat_person和flat_group结构。我在这里几乎没有检查流长度,小心,这对于一个工作代码来说是非常必要的。

typedef struct person {
size_t name_size;
const char name[];
} flat_person;
typedef struct {
size_t caption_size;
const char caption[];
} flat_group_caption;
typedef struct {
size_t group_size;
flat_person people[];
} flat_group;
group *read_group(const void *stream, size_t len) {
const char *curr_pos_in_stream = stream;
/* considering you have a group struct with 'traditional' linked
* lists to hold several persons */
group *g = malloc(sizeof(*g));
const flat_group_caption *fgc = stream;
/* Check if stream can hold the size of caption and then the
* declared caption itself */
if (len < sizeof(fgc->caption_size)
|| len < sizeof(fgc->caption_size) + fgc->caption_size)
return NULL;
group_add_caption(g, fgc->caption, fgc->caption_size);
curr_pos_in_stream += sizeof(fgc->caption_size) + fgc->caption_size;
len -= sizeof(fgc->caption_size) + fgc->caption_size;
flat_group *fg = (void *)curr_pos_in_stream;
curr_pos_in_stream += sizeof(fg->group_size);
/* FIXME check len is still big enougth */
len -= sizeof(fg->group_size);
for (size_t i = 0; i < fg->group_size; i++) {
const flat_person *fp = (void *)curr_pos_in_stream;
if (len < sizeof(fp->name_size)
|| len < sizeof(fp->name_size) + fp->name_size) {
free(g);
return NULL;
}
person *p = malloc(sizeof(*p));
person_add_name(p, fp->name, fp->name_size);
group_add_person(g, p); // would add the person in the linked list held by group
curr_pos_in_stream += sizeof(fp->name_size) + fp->name_size;
/* FIXME check len is still big enougth */
len -= sizeof(fp->name_size) + fp->name_size;
}
return g;
}

希望这能帮助。。。

最新更新