柔性数组


最近看书看到一段这样的代码如下

#include <iostream>
#include <string.h>
#include <malloc.h>
using namespace std;
void main()
{
    typedef struct _rect
    {
    int left;
    int right;
    int top;
    int bottom;
    } RECT;
    typedef struct _RGNDATA{
        RECT rect;
        char Buffer[1];
    }RGNDATA;
    RGNDATA *region_data;
    region_data=(RGNDATA *)malloc(sizeof(RECT)+3*sizeof(RECT));
    RECT rect_list[3]={
        {10,10,50,50},
        {100,100,200,200},
        {300,300,500,450}
    };
    memcpy(region_data->Buffer,rect_list,sizeof(RECT)*3);
    cout < <sizeof(region_data->Buffer) < <endl;
    for(int i=0;i <50;i++)
    cout < <region_data->Buffer < <endl;
}

如果我把程序稍微更改下,就是把Buffer这个char数组单独定义,给他开辟空间,具体如下:

#include <iostream>
#include <string.h>
#include <malloc.h>
using namespace std;
void main()
{
    typedef struct _rect
    {
    int left;
    int right;
    int top;
    int bottom;
    } RECT;
    char Buffer[1];
    RECT rect_list[3]={
        {10,10,50,50},
        {100,100,200,200},
        {300,300,500,450}
    };
    memcpy(Buffer,rect_list,sizeof(RECT)*3);
    cout < <sizeof(Buffer) < <endl;
    cout < <Buffer[0] < <endl;
}

程序运行的时候就会崩溃,原因也很简单就是memcpy(Buffer,rect_list,sizeof(RECT)*3);的时候,Buffer越界了。虽然第一段代码也确定Buffer数组的长度为1,但是程序可以在运行的时候,动态的给Buffer增加长度。而如果你单独定义Buffer就不能用sizeof动态的增加长度。我查了一些资料上面说是因为你在第一段代码中是sizeof结构体的大小,所以他就会为你结构体中的Buffer动态分配长度。而后面的代码你是sizeof char数组的大小,因为已经是1了,sizeof的时候会报错。自己就上网随便到论坛逛了一下,结果被高手鄙视了一下算是明白了。下面就引用下别人的帖子。 柔性数组结构成员 C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员,但结构中的柔性数组成员前面必须至少一个其 他成员。柔性数组成员允许结构中包含一个大小可变的数组。sizeof返回的这种结构大小不包括柔性数组的内存。包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小

C语言大全,”柔性数组成员” 看看 C99 标准中 灵活数组成员: 结构体变长的妙用——0个元素的数组 有时我们需要产生一个结构体,实现了一种可变长度的结构。如何来实现呢? 看这个结构体的定义:

typedef struct st_type
{
int nCnt;
int item[0];
}type_a;

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

typedef struct st_type
{
int nCnt;
int item[];
}type_a;

这样我们就可以定义一个可变长的结构,用sizeof(type_a)得到的只有4,就是sizeof(nCnt)=sizeof(int)那 个0个元素的数组没有占用空间,而后我们可以进行变长操作了。 C语言版:

type_a *p = (type_a*)malloc(sizeof(type_a)+100*sizeof(int));

C++语言版:

type_a *p = (type_a*)new char[sizeof(type_a)+100*sizeof(int)];

这样我们就产生了一个长为100的type_a类型的东西用p->item[n]就能简单地访问可变长元素,原理十分简单 ,分配了比sizeof(type_a)多的内存后int item[];就有了其意义了,它指向的是int nCnt;后面的内容,是没 有内存需要的,而在分配时多分配的内存就可以由其来操控,是个十分好用的技巧。 而释放同样简单: C语言版: free(p); C++语言版: delete []p; 其实这个叫灵活数组成员(fleible array member)C89不支持这种东西,C99把它作为一种特例加入了标准。但 是,C99所支持的是incomplete type,而不是zero array,形同int item[0];这种形式是非法的,C99支持的 形式是形同int item[];只不过有些编译器把int item[0];作为非标准扩展来支持,而且在C99发布之前已经有 了这种非标准扩展了,C99发布之后,有些编译器把两者合而为一。 这篇帖子参考出处: 柔性数组结构成员

这下你算是彻底明白了吧!原来都是柔性数组惹的祸啊!看来自己c语言的功底太差了。惭愧之 !

如果你喜欢这篇文章,谢谢你的赞赏

图3

如有疑问请联系我