C99标准中,结构体中的最后一个元素可以是未知大小的数组,这个数组就叫做柔性数组成员(其前面至少要存在一个其他成员)。
一、概念 在C99中,结构体中的最后一个元素可以是未知大小的数组,这个数组就叫做柔性数组成员,也称伸缩性数组成员,其前面至少要存在一个其他成员。官方说明:As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member.
。C99支持incomplete type
即int a[]
格式,不支持zero array
即int a[0]
格式(有的编译器支持)。关于incomplete说明:incomplete types(types that describe objects but lack information needed to determine their sizes).
。柔性数组成员特性如下:
柔性数组不占内存,即sizeof
返回的这种结构体大小时不包括柔性数组的内存
柔性数组成员必须定义在结构体里面且为最后元素
结构体中不能单独只有柔性数组成员
包含柔性数组成员的结构体用malloc()
函数进行内存的动态分配,并且分配的内存应该大于结构的大小以适应柔性数组的预期大小。
二、使用 C语言数据类型可分为四大类,即基本类型(数值类型(又分为整型和实数型)、字符串)、构造类型(数组、结构体、共用体、枚举)、指针类型、空类型。对于大部分数据类型,在其声明后所占的内存空间就已确定,如char a
占1个字节,int b[10]
则占40个字节,结构体所占内存为成员所占空间的总和(不考虑内存对齐的情况,实际不是取的和),共用体则为最大成员的所占的空间。
结构体是比较常用的一种数据类型,有时需要在结构体中存放一个长度是动态的成员,此时一般又两种做法:
方式一:定义一个指针成员,指针指向动态的内存空间 方式二:使用柔性数组成员
指针成员方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stddef.h> // #pragma pack(32); typedef struct Test { long double b; int a; char *p; } Test; int main() { Test *t = (Test *)malloc(sizeof(Test)); char *str = (char *)malloc(sizeof(char) * 10); strcpy(str, "hello"); t->p = str; printf("指针p的内容:%s\n", (t->p)); printf("t的地址为:%p\n", t); printf("char *大小为:%d\n", sizeof(char *)); printf("t.b的地址为:\t%p\n", &(t->b)); printf("t.a的地址为:\t%p\n", &(t->a)); printf("t.p本身的地址为:%p\n", &(t->p)); printf("t.p内容的地址为:%p\n", (t->p)); printf("t.b的偏移量为:%d\n", offsetof(struct Test, b)); printf("t.a的偏移量为:%d\n", offsetof(struct Test, a)); printf("t.p的偏移量为:%d\n", offsetof(struct Test, p));//64位机器指针固定占8个字节 printf("t的内存大小为:%lu", sizeof(Test)); free(t); free(t->p); return 0; }
通过以上代码可知,使用此方式分配和释放内存都需要进行两次。运行后可知,结构体内存和指针p指向的字符串内存是不连续的,
柔性数组方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <string.h> #include <stdlib.h> typedef struct Test { int a; char p[]; } Test; int main() { Test *t = (Test*)malloc(sizeof(Test) + sizeof(char) * (10+1)); strcpy(t->p, "hello"); printf("%s\n", (t->p)); printf("Address:\n"); printf("t\t %p\n", t); printf("t.a\t %p\n", &(t->a)); printf("t.p\t %p\n", (t->p)); free(t); return 0; }
三、参考
参考一
参考二