这两种实现有何不同:
struct queue {
int a;
int b;
q_info *array;
};
和
struct queue {
int a;
int b;
q_info array[0];
};
这两种实现有何不同:
struct queue {
int a;
int b;
q_info *array;
};
和
struct queue {
int a;
int b;
q_info array[0];
};
第二个struct
不使用零元素数组 - 这是 C99 之前的技巧,用于制作灵活的数组成员。不同之处在于,在第一个片段中,您需要两个malloc
s - 一个用于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[];
};
这些是完全不同的事情:
人们这样做的原因是它更节省空间。您只需过度分配结构所需的内存,然后假装数组有更多元素然后声明 - 编译器不会介意(通常)。
这也意味着您可以减少一个用于取消引用的指针,并且您可以为结构和数组同时分配和释放内存。
显然,这个技巧只有在数组是结构中的最后一个元素时才有效。
在第一个中实际上分配了一个指针struct queue
,并且sizeof(struct queue) == 2 * sizeof(int) + sizeof(q_info*)
在第二个中,没有指针或任何命名的东西array
真正存在于struct queue
, 和sizeof(struct queue) == 2 * sizeof(int)
中。这被称为在使用之前或之后方便地引用数据的技巧array
。我在实现内存分配器时使用了这个技巧。
对于大小为零的数组成员,您可以在分配结构时分配比struct queue
(例如malloc(sizeof(struct queue) + sizeof(q_info) * 10)
)的大小更多的内存,以获得可以使用的连续内存区域。然后数组将成为分配的内存的一部分,对于示例分配,您有十个q_info
条目。
对于指针,您必须进行两次分配,一次分配给queue
结构,一次分配给array
成员。您当然必须调用free
两次,一次用于array
指针,一次用于结构。
但是,一旦分配,两者都可以使用相同的。
q_info array[0];
由于自动转换而衰减为指针。但是,它是不可分配的。你不能说
array = <some address of an object>;
然后。