跳至主要內容

柔性数组

马龙伟...大约 3 分钟笔记C/C++

参考链接

C语言中的柔性数组 C语言结构体中char[0]和char[1]的用法open in new window

实现机制

在结构体最后加 char[0]char[1] 的用法是GNU C的扩展,在ISO/IEC 9899-1999里面,这么写是非法的。

这种用法在C99中叫做 柔性数组。柔性数组成员前面必须至少有一个其它类型成员。包含柔性数组成员的结构要用malloc进行动态内存分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

相关信息

主要是为了方便管理内存缓冲区,如果你直接使用指针而不使用数组,那么,你在分配内存缓冲区时,就必须分配结构体一次,然后再分配结构体内的指针一次,(而此时分配的内存已经与结构体的内存不连续了,所以要分别管理即申请和释放)而如果使用数组,那么只需要一次就可以全部分配出来,反过来,释放时也是一样,使用数组,一次释放,使用指针,得先释放结构体内的指针,再释放结构体。还不能颠倒次序。

其实就是 分配一段连续的的内存,减少内存的碎片化

代码实现

struct Msg
{
    ...         // 其它成员
    ...         // 其它成员
    int nLen;   // 一般char data[0]的前面会加一个长度nLen表示data的大小
    char data[0];   // char[0]或char[1]必须放在最后
};

我们要知道的一点就是:char data[0] 这个数组是没有元素的,它的地址紧跟着nLen后的地址,如果分配的内存大于结构体的实际大小,那么大出来的那部分就是data的内容

实际使用时,一般这样用

int dataBytes = 10;             // 此处指定data的数据大小
struct Msg *p = (struct Msg *)malloc(sizeof(struct Msg) + dataBytes);   // 动态分配
p->nLen       = dataBytes;      // 把长度赋值给nLen,以方便其它部分使用此结构体

C99 使用不完整类型实现柔性数组

在C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组(flexible array)成员(也叫伸缩性数组成员),但结构中的柔性数组成员前面必须至少一个其他成员。柔性数组成员允许结构中包含一个大小可变的数组。

柔性数组成员只作为一个符号地址存在,而且必须是结构体的最后一个成员,sizeof 返回的这种结构大小不包括柔性数组的内存。柔性数组成员不仅可以用于字符数组,还可以是元素为其它类型的数组。

包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

柔性数组的使用请看下面的例子:

typedef struct test
{
    int a;
    double b;
    char c[0];
};

有些编译器会报错无法编译可以改成:

typedef struct test
{
    int a;
    double b;
    char c[];
};

相关信息

应当尽量使用标准形式,在非C99的场合,可以使用指针方法。

需要说明的是:C89不支持这种东西,C99把它作为一种特例加入了标准。

但是,C99所支持的是incomplete type,而不是zero array,形同int a[0];这种形式是非法的,C99 支持的形式是形同int a[];只不过有些编译器把int a[0];作为非标准扩展来支持,而且在C99 发布之前已经有了这种非标准扩展了,C99 发布之后,有些编译器把两者合而为一了。

你认为这篇文章怎么样?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.5