今天在看android系统源码时发现一个很有趣的结构体,以前从来没发现数组的长度可以为0,既然碰见这种情况,就好好分析一下。
如下结构体:
struct example
{
int length;
char name[0];
};
原来,长度为0的数组在标准c和c++中是不允许的,使用VC编译器是编译不过的,它会提示数组长度不能为0。但在GCC编译器中是可以编译通过的,它的最典型的用法就是位于数组中的最后一项,这样做主要是为了方便内存缓冲区的管理。
通过查看gcc手册了解到,可以采用如下方式对其申请内存空间:
struct example myExample = (struct example )malloc (sizeof (struct example) + this_length);
myExample->length= this_length;
这样的写法最适合制作动态buffer,直接就把buffer的结构体和缓冲区一块分配了。用起来也非常方便,为什么要使用长度为0的数组呢?它有什么好处?
如果你将上面的长度为0的数组换成指针,那么在分配内存时,需采用两步:首先,需为结构体分配一块内存空间;其次再为结构体中的指针分配内存空间,一般使用malloc函数动态分配内存空间,那么这段存储空间是分配在堆中,而不是在栈中,这样两次分配的内存是不连续的,需要分别对其进行管理。
当使用长度为0的数组时,则是采用一次分配的原则,一次性将所需的内存全部分配给它。相反,释放时也是一样的。
假设如下结构体:
struct sample
{
int length;
char * name;
}
则使用时需使用如下语句:
struct sample * example = (struct sample *)malloc(sizeof(struct sample));
example->length = size;
example->name =(char *)malloc(size);
而释放内存时,使用长度为0的数组释放是:
free(example);
而指针方式则
free(example->name);
free(example);
从上面的比较可以看书出:,使用长度为0的数组可以达到更简单的效果,同时节省了空间。由于空数组不占内存空间,因此这样的结构节省空间,且无需初始化,数组名就是后面元素的地址,直接就能当做指针使用。