4

这两种实现有何不同:

struct queue {
    int a;
    int b;
    q_info *array;
};

struct queue {
    int a;
    int b;
    q_info array[0];
};
4

5 回答 5

11

第二个struct不使用零元素数组 - 这是 C99 之前的技巧,用于制作灵活的数组成员。不同之处在于,在第一个片段中,您需要两个mallocs - 一个用于struct,一个用于array,而在第二个片段中,您可以同时完成这两个malloc

size_t num_entries = 100;
struct queue *myQueue = malloc(sizeof(struct queue)+sizeof(q_info)*num_entries);

代替

size_t num_entries = 100;
struct queue *myQueue = malloc(sizeof(struct queue));
myQueue->array = malloc(sizeof(q_info)*num_entries);

这可以让您节省解除分配的次数,提供更好的引用局部性,还可以节省一个指针的空间。

从 C99 开始,您可以从数组成员的声明中删除零:

struct queue {
    int a;
    int b;
    q_info array[];
};
于 2013-10-10T10:46:57.600 回答
2

这些是完全不同的事情:

  • 第一个包含指向外部数组的指针。
  • 第二个是恰好有零个元素的内联数组。

人们这样做的原因是它更节省空间。您只需过度分配结构所需的内存,然后假装数组有更多元素然后声明 - 编译器不会介意(通常)。

这也意味着您可以减少一个用于取消引用的指针,并且您可以为结构和数组同时分配和释放内存。

显然,这个技巧只有在数组是结构中的最后一个元素时才有效。

于 2013-10-10T10:46:42.843 回答
1

在第一个中实际上分配了一个指针struct queue,并且sizeof(struct queue) == 2 * sizeof(int) + sizeof(q_info*)

在第二个中,没有指针或任何命名的东西array真正存在于struct queue, 和sizeof(struct queue) == 2 * sizeof(int)中。这被称为在使用之前或之后方便地引用数据的技巧array。我在实现内存分配器时使用了这个技巧。

于 2013-10-10T10:46:49.837 回答
1

对于大小为零的数组成员,您可以在分配结构时分配比struct queue(例如malloc(sizeof(struct queue) + sizeof(q_info) * 10))的大小更多的内存,以获得可以使用的连续内存区域。然后数组将成为分配的内存的一部分,对于示例分配,您有十个q_info条目。

对于指针,您必须进行两次分配,一次分配给queue结构,一次分配给array成员。您当然必须调用free两次,一次用于array指针,一次用于结构。

但是,一旦分配,两者都可以使用相同的。

于 2013-10-10T10:48:36.793 回答
0
q_info array[0];

由于自动转换而衰减为指针。但是,它是不可分配的。你不能说

array = <some address of an object>;

然后。

于 2013-10-10T10:53:47.480 回答