最近看书看到一段这样的代码如下
#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语言的功底太差了。惭愧之 !