柔性数组是指在结构体中定义一个为指定大小的数组。
1,在结构体中,柔性数组的前面至少有一个成员。
例如
struct S
{
int i;
char c;
int arr[0];
};
2,再用sizeof 计算结构体大小的时候,会发现结构体的大小不包括柔性数组的大小。
int main()
{
printf("%zu\n", sizeof(struct S));
return 0;
}

3,在给结构体用malloc开辟空间的时候,开辟的空间应大于结构体的大小,以适应柔性数组的大小。
struct S* s = NULL;
s = (struct S*)malloc(sizeof(struct S)+sizeof(int)*10);
if (s == NULL)
{
return 1;
}
else
{
//......
}
在开辟内存空间的时候,一般采用上述方式,结构体大小+要给柔性数组开辟的空间。
1,给柔性数组初始化
struct S* s = NULL;
s = (struct S*)malloc(sizeof(struct S)+sizeof(int)*10);
if (s == NULL)
{
return 1;
}
else
{
int i = 0;
for (i = 0; i < 10; i++)
{
s->arr[i] = i;
}
for (i = 0; i < 10; i++)
{
printf("%d ", s->arr[i]);
}
}
free(s);
s = NULL;

2,柔性数组改变数组的大小(realloc)
struct S* ptr = (struct S*)realloc(s,sizeof(struct S) + sizeof(int) * 20);
if (ptr != NULL)
{
s = ptr;
ptr = NULL;
for (i = 10; i < 20; i++)
{
s->arr[i] = i;
}
for (i = 0; i < 20; i++)
{
printf("%d ", s->arr[i]);
}
}
free(s);
s = NULL;

有的人会有疑问,不用柔性数组也可以完成以上操作啊。
struct s
{
int i;
char c;
int* arr;
};
结构体中放一个指针也能完成上述操作。
struct s* p = NULL;
int i = 0;
p = (struct s*)malloc(sizeof(struct s));
if (p == NULL)
{
return;
}
else
{
p->arr = (int*)malloc(sizeof(int) * 10);
if (p != NULL)
{
for (i = 0; i < 10; i++)
{
p->arr[i] = i;
}
for (i = 0; i < 10; i++)
{
printf("%d ", p->arr[i]);
}
}
printf("\n");
int* ptr = (int*)realloc(p->arr, sizeof(int) * 20);
if (ptr != NULL)
{
p->arr = ptr;
ptr = NULL;
}
for (i = 10; i < 20; i++)
{
p->arr[i] = i;
}
for (i = 0; i < 20; i++)
{
printf("%d ", p->arr[i]);
}
free(p->arr);
p->arr = NULL;
free(p);
p = NULL;
}

可以看到这种做法完全可以替代柔性数组,但是柔性数组有何优点呢?
总结: 1,柔性数组开辟的空间在释放的时候只需要free一次即可,而上述这种方法在释放空间的时候需要free两次。
2,柔性数组开辟的空间是连续的,利于提高访问速度。


我们先看段代码
#include
struct str{
int len;
char s[0];
};
struct foo {
struct str *a;
};
int main(int argc, char** argv) {
struct foo f={0};
if (f.a->s) {
printf( f.a->s);
}
return 0;
}
当你调试的时候你会发现会在printf(f.a->s)这行代码出挂掉。


当你把代码改成 printf(“%x\n”, f.a->s); 的时候你会发现代码能跑了

但是这个4是什么意思呢?貌似是柔性数组对结构体变量的偏移量啊!!!

但是有朋友会产生疑问,明明这行代码解引用空指针了啊,怎么能跑过呢?
事实上,在访问结构体变量成员的时候实质不管结构体的示例是什么,访问其成员的时候就是加成员的偏移量
但是你将结构体成员中的数组换成指针,的时候在跑这个代码你又会发现问题——这次在if语句的时候就挂掉了。不信你可以试一下。
所以这就是结构体中指针与数组名的区别
访问成员数组名其实得到的是数组的相对地址,而访问成员指针其实是相对地址里的内容(这和访问其它非指针或数组的变量是一样的)
这里你就知道,为啥将数组换成指针就会在在if语句的时候挂掉了吧(输出起始地址为4的内容,这是不能让我们访问的空间),还有上面解引用空指针的疑惑(我们说的不能接引用空指针,是指解引用空指针得到里面的内容,而这里是得到相对地址)。