1. 柔性数组的来源
有时候需要在结构体中存放一个长度动态的字符串,一般的做法,是在结构体中定义一个指针成员,这个指针成员指向该字符串所在的动态内存空间
typedef struct s_
test
{
int a;
double b;
char *p;
};
p指向字符串。这种方法造成字符串与结构体是分离的,不利于操作。如果把字符串跟结构体直接连在一起,不是更好吗?
即申请一块动态内存空间,这段连续的空间包括结构体以及p所指向的数据。
char* str="hello"; struct s_test *ptest = (struct s_test*)malloc(sizeof(s_test)+streln(str)+1);
strcpy(ptest+1,str);
(char*)(ptest + 1)就是字符串“hello”的地址
2.柔性数组原型
上例中p成了多余的东西,可以去掉。
但是,又产生了另外一个问题:老是使用(char*)(ptestt + 1)不方便。如果能够找出一种方法,既能直接引用该字符串,又不占用结构体的空间,就完美了,符合这种条件的代码结构应该是一个非对象的符号地址,在结构体的尾部放置一个0长度的数组是一个绝妙的解决方案。不过,C/C++标准规定不能定义长度为0的数组,因此,有些编译器就把0长度的数组成员作为自己的非标准扩展,例如:
typedef struct s_
test
{ int a; double b; char c[0]; };
c就叫柔性数组成员,如果把ptest指向的动态分配内存看作一个整体,c就是一个长度可以动态变化的结构体成员,柔性一词来源于此。c的长度为0,因此它不占用test的空间,同时ptest->c就是“hello world”的首地址,不需要再使用(char*)(ptestt + 1)这么丑陋的语法了。
C99使用不完整类型实现柔性数组成员,标准形式是这样的:
struct s_test { int a; double b; char c[]; };
c同样不占用test的空间,只作为一个符号地址存在,而且必须是结构体的最后一个成员
完整实验一:
#include <stdlib.h> #include <string.h> struct line { int length; char contents[0]; };// C99的玩法是:char contents[]; 没有指定数组长度 int main(int argc, char *argv[]) { int this_length=10; struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length); thisline->length = this_length; memset(thisline->contents, 'a', this_length); printf("%s",thisline->contents); return 0; }
实验结果为:aaaaaaaaaa
上面这段代码的意思是:我想分配一个不定长的数组,于是我有一个结构体,其中有两个成员,一个是length,代表数组的长度,一个是contents,代码数组的内容。后面代码里的 this_length(长度是10)代表是想分配的数据的长度。
原文:http://www.jb51.net/article/54960.htm