指针和数组在结构中使用零元素之间的区别

两种实现有何不同:

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

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

第二个struct不使用零元素数组 – 这是制作灵活数组成员的前C99技巧。 区别在于,在第一个片段中,您需要两个malloc – 一个用于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需要的内存,然后假装数组有更多的元素然后声明 – 编译器不介意(通常)。

它还意味着你只需要一个指向取消引用的指针,并且可以为结构和数组分配和释放内存。

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

在第一个实际上,在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) )以具有连续区域你可以使用的记忆。 然后,该数组将成为分配的内存的一部分,对于示例分配,您将在其中包含10个q_info条目。

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

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

 q_info array[0]; 

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

 array = ; 

然后。