关于柔性数组

1. 写在前面

    

前一段在看百度阿拉丁底层存储的时候,看到这样一段代码:

struct dlist_t
{
    dlist_t *next;
    u_int key;
    int size[0];
};

      印象中int size[0]这种在C/C++是不允许的,但是在结构中确实可以使用的(C99标准)。经过查看资料,知道这种可变数组被称为柔性数组。

2. 用法说明

    C99的标准形式如下

struct sample
{
       int a;
       double b;
       char c[]; //或者 char c[0]
};

      在结构体的最后,可以加入一个长度为0的数组c,这个数组c就是所谓的柔性数组。c只是一个偏移,通过动态申请c的大小可以达到动态结构的效果。

3. 例子

#include<cstring>
#include<iostream>
using namespace std;

#define uint32 unsigned int


typedef struct _normal_array_t
{
    char a;
    uint32 b;
    int *c;
}__attribute ((packed)) normal_array_t;

typedef struct _dynamic_array_t
{
    char a;
    uint32 b;
    int c[]; 
}__attribute ((packed)) dynamic_array_t;

int main()
{
    normal_array_t* n1 = (normal_array_t*)malloc(sizeof(normal_array_t) );
    cout << "n1: before malloc size is " << sizeof(*n1) << endl;
    n1->c = (int*) malloc(100);
    n1->c[50] =  100;
    cout << "n1: after malloc c, n1->c[50] is " << n1->c[50] << endl;
    cout << "n1: after malloc c, size is " << sizeof(*n1) << endl;
    free(n1->c);
    free(n1);

    dynamic_array_t* d1 = (dynamic_array_t*)malloc(sizeof(dynamic_array_t) + 100 * sizeof(int) );
    cout << "d1: size is " << sizeof(*d1) << endl;
    d1->c[50] = 200;
    cout << "d1: d1->c[50] is " << d1->c[50] << endl;
    free(d1);
}

   结果如下:

[email protected]:~/test$ ./dynamic 
n1: before malloc size is 13
n1: after malloc c, n1->c[50] is 100
n1: after malloc c, size is 13
d1: size is 5
d1: d1->c[50] is 200

      如上图,我们如果想在struct里面声明一个动态的数组,可以有2种方式(里面的__attribute ((packed)) 是禁止编译器做字节对齐,效果明显).

      第一种如下所示,这种方法可以先申请normal_array_t自身,然后在申请normal_array_t->c,然后通过normal_array_t->c[index]来访问动态数组,使用之后,需要先free(normal_array_t->c),然后再free(normal_array_t);

      我的机器是64位,所以指针为8个字节,进而normal_array_t大小为13.

typedef struct _normal_array_t
{
    char a;
    uint32 b;
    int *c;
}__attribute ((packed)) normal_array_t;

     第二种方法如下所示,这种方法一次性申请normal_array_t加上需要动态数组的大小来申请一整块内存,然后通过dynamic_array_t->c[index]来访问动态数组,使用之后,需要先free(dynamic_array_t)就可以释放整个内存。

     可以看到dynamic_array_t->c仅仅是一个符号,dynamic_array_t的大小为5(char1, uint32 4)。

typedef struct _normal_array_t
{
    char a;
    uint32 b;
    int *c;
}__attribute ((packed)) normal_array_t;

4. 小结

     可以看到使用柔性数组可以大大简化内容的管理,只需要一次申请,然后通过数组的指针偏移就可以直接获得相应的数据缓冲区,非常简单,释放的时候也仅仅只需要一次释放。

你可能感兴趣的:(C++,柔性数组)