变长结构体

变长结构体

 

变长结构体是由gcc扩展的一种技术,它是指其最后一个成员的长度不固定flexible array member,也叫柔性数组,先来看一个简单的例子:

#include <stdlib.h>
#include <stdio.h>

#pragma pack(1)
typedef struct {
    int a;
    char b[10];
    char *vector;         
} cq; 
#pragma pack()

int main()
{
    cq *a = malloc(sizeof(cq));

    char str[] = "hello";

    a->vector = malloc(sizeof(str));
    memcpy(a->vector, str, sizeof(str));

    printf("%s\n", a->vector);       // "hello"
    printf("%d\n", sizeof(cq));      // 22

    free(a->vector);
    free(a);

    return 0;
}

这段代码中,结构体cq中的成员vector是一个指针,你在分配内存缓冲区时,就必须分配结构体一次,然后再分配结构体内的指针一次,(而此时分配的内存已经与结构体的内存不连续了,所以要分别管理即申请和释放)。

而如果使用数组,那么只需要一次就可以全部分配出来,(见下面的例子),反过来,释放时也是一样,一次释放。而使用指针,得先释放结构体内的指针,再释放结构体。还不能颠倒次序。其次,就是分配一段连续的的内存,减少内存的碎片化。

 

#include <stdlib.h>
#include <stdio.h>

#pragma pack(1)
typedef struct {
    int a;
    char b[10];
    char vector[0];         // 可变数组
} cq; 
#pragma pack()

int main()
{
    char str[] = "hello";

    cq *a = malloc(sizeof(cq) + sizeof(str));   // decide amount used
    memcpy(a->vector, str, sizeof(str));

    printf("%s\n", a->vector);       // "hello"
    printf("%d\n", sizeof(cq));      // 14

    free(a);

    return 0;
}

例子中,打印出的结构体长度是14(为成员a和b的长度之和),——变长数组vector不占结构体的空间!

可见,变长结构体是能让我们在分配时再决定其大小,而不是在定义时就要固定其数组长度。

 

可变数组的一种更通用的用法是用一个成员指明变长数组的长度,方便在其他地方读取数组内容。

struct line {
   int length;
   char contents[0];
};

struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length);
thisline->length = this_length;

 

 

最后,转述一段C99标准(draft N1570)对这个问题的描述,本人英文很烂,就不翻译了。

As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply. However, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array. If this array would have no elements, it behaves as if it had one element but the behavior is undefined if any attempt is made to access that element or to generate a pointer one past it.

 

参考:

http://stackoverflow.com/questions/11733981/what-is-the-purpose-of-a-zero-length-array-in-a-struct

 

 

 

 

 

 

 

posted @ 2014-04-10 23:39  如果的事  阅读(2454)  评论(0编辑  收藏  举报