C语言0长度数组(柔性数组)
2014-06-18 15:13
197 查看
0长度数组,又称为柔性数组(flexible array),通常用来实现变长数组,常见于TLV(type-length-value)的数据结构中。在标准 C 和 C++ 中,不允许用 0 长度数组,但在
GNU C 中,却可以定义 0 长度数组(在C99之前写成长度为0,C99中可以直接不写索引)。通常会拿手册中给的例子来说明
struct line {
int length;
char contents[0]; // char contents[]; //C99
}
从打印出来的结构体尺寸 sizeof (struct line) = 4 (和编译器有关,看内存对齐规则),可以看到contents[0]不占有空间(不同于字符指针类型),它存在的好处是在结构体的后面允许我们自己申请一定大小的存储空间,而不是每次都使用 MAX_SIZE 大小的结构体。通常的使用方法如下:
int this_length = 60;
struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length);
thisline->length = this_length;
通过测试代码可以发现:为0长度数组分配的空间紧跟着该该结构体最后一个字段之后,而且释放结构体指针后,我们自己分配的空间也会释放(不同于有些网上的说法)。所以需要注意的是我们释放的是由某个指针指向的内存空间,而非指针,指针变量是在程序结束后回收的,所以在我们释放一段内存之后要将其置为NULL,否则还是可以访问的,不过访问到的都是垃圾数据。
测试代码:FlexibleArray.c
运行效果:
update:2015-4-8
FlexibleArray2.c
可以看到根本无法修改一个实例中contents的指向,所以占用的是完整的内存区间,不能指向单独的地址空间。
FlexibleArray3.c
可以看到严格的弹性数组和长度0的数组还是有区别的,这里就不能使用静态初始化,只能像FlexibleArray1.c中那样操作。
GNU C 中,却可以定义 0 长度数组(在C99之前写成长度为0,C99中可以直接不写索引)。通常会拿手册中给的例子来说明
struct line {
int length;
char contents[0]; // char contents[]; //C99
}
从打印出来的结构体尺寸 sizeof (struct line) = 4 (和编译器有关,看内存对齐规则),可以看到contents[0]不占有空间(不同于字符指针类型),它存在的好处是在结构体的后面允许我们自己申请一定大小的存储空间,而不是每次都使用 MAX_SIZE 大小的结构体。通常的使用方法如下:
int this_length = 60;
struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length);
thisline->length = this_length;
通过测试代码可以发现:为0长度数组分配的空间紧跟着该该结构体最后一个字段之后,而且释放结构体指针后,我们自己分配的空间也会释放(不同于有些网上的说法)。所以需要注意的是我们释放的是由某个指针指向的内存空间,而非指针,指针变量是在程序结束后回收的,所以在我们释放一段内存之后要将其置为NULL,否则还是可以访问的,不过访问到的都是垃圾数据。
测试代码:FlexibleArray.c
#include <stdio.h> #include <stdlib.h> struct line { int length; char test; char contents[0];//or <span style="font-family: Arial, Helvetica, sans-serif;">char contents[];</span> }; int main(){ int i; int this_length = 60; struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length); thisline->length = this_length; printf ("thisline addr is %p\n", thisline); printf ("thisline->length field value is %d\n",thisline->length); printf ("thisline->length field addr is %p\n", &thisline->length); printf ("thisline->test field addr is %p\n", &thisline->test); printf ("thisline->contents field addr is %p\n", &thisline->contents); printf ("thisline->contents[0] addr is %p\n", &thisline->contents[0]); printf ("thisline->contents[0] addr is %p\n", &thisline->contents[1]); for(i=0; i<3; i++){ thisline->contents[i] = 'a' + i; } char *p = thisline->contents; printf("%c\n", p[2]); free(thisline); //After free , when we access the space ,we got garbage data; printf("%d\n", thisline->length); printf("%c\n", p[2]); return 0; }
运行效果:
update:2015-4-8
FlexibleArray2.c
#include <stdio.h> #include <stdlib.h> #include <string.h> struct line { int length; char test; char contents[0]; }; int main(){ int i; char s[20] = "Hello World."; int that_length = 60; struct line thisline = {5, 'A', {'a', 'b', 'c'}}; struct line *thatline = malloc(sizeof(struct line) + that_length); thatline->length = that_length; for(i=0; i<3; i++){ thatline->contents[i] = 'A' + i; } char *p = thatline->contents; printf("%c\n", p[2]); free(thatline->contents); thatline->contents = thisline.contents; // error: incompatible types when assigning to type ‘char[]’ from type ‘char *’ p = thatline->contents; printf("%c\n", p[2]); return 0; }
可以看到根本无法修改一个实例中contents的指向,所以占用的是完整的内存区间,不能指向单独的地址空间。
FlexibleArray3.c
#include <stdio.h> #include <stdlib.h> #include <string.h> struct line { int length; char test; char contents[]; }; int main(){ struct line thisline = {5, 'A', {'a', 'b', 'c'}}; return 0; }
可以看到严格的弹性数组和长度0的数组还是有区别的,这里就不能使用静态初始化,只能像FlexibleArray1.c中那样操作。
相关文章推荐
- C语言0长度数组(可变数组/柔性数组)详解
- C语言0长度数组(柔性数组)
- C语言应用于LR中-如何得到数组长度(原创)
- C语言中如何不用STRLEN检测数组长度
- C语言中计算一个数组长度
- C语言中,当计算字符数组长度时,用sizeof 和strlen 的原理及两者的区别
- C语言中的柔性数组结构
- C语言中如何求任意一个int型数组的长度
- C语言 数组长度函数
- c语言中求数组的长度
- c语言 求解数组长度
- C语言中如何求任意一个int型数组的长度?
- c语言中长度为0的数组妙用
- 【原创】C语言中如何用长度变量定义数组
- 【原创】C语言中如何用长度变量定义数组
- C语言中长度为0的数组
- C语言中如何求任意一个int型数组的长度?
- C语言中如何求任意一个int型数组的长度?
- C语言的柔性数组运用解析
- C语言用堆和双向链表实现可变长度数组