一、柔性数组是什么?
柔性数组是 C 语言里的一种结构体成员,它允许结构体的最后一个成员是一个大小可变的数组。它的大小在结构体定义时不占空间,真正的内存分配在运行时决定。
它的语法是:
plaintext
struct xxx {
...
type arr[]; // 柔性数组成员,必须是结构体最后一个成员
};
二、柔性数组的特点:
- 结构体中必须是最后一个成员
- 数组大小写 [] ,不写数字
- 结构体本身不包含数组空间
- 实际使用时要 malloc 结构体 + 数组的总大小
- 可以动态扩展,比指针方式更省内存、更高效
三、为什么要用柔性数组?
下面是它的三大优势:
- 节省内存(避免指针占用额外空间)
如果用指针:
plaintext
struct A {
int len;
int *data; // 额外 8 字节指针
};
而柔性数组不需要指针:
plaintext
struct A {
int len;
int data[]; // 不占空间
};
- 内存连续,访问更快
指针方式需要两次内存访问:
指针 → 数据
柔性数组是一次访问:
结构体内存直接连着数据
- 更方便管理内存
只需一次 malloc ,一次 free
不用像指针方式那样分别分配结构体和数据
柔性数组的正确用法(完整示例)
下面这段代码你可以直接复制到 Linux 或 Windows 下运行。
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义柔性数组成员的结构体
struct FlexBuf {
int len; // 有效元素个数
int data[]; // 柔性数组成员,不占空间
};
int main() {
int n = 5; // 我们想要 5 个 int 的数组
// 1. 分配内存
// sizeof(struct FlexBuf) + n * sizeof(int)
struct FlexBuf *fb = malloc(sizeof(struct FlexBuf) + n * sizeof(int));
if (!fb) {
perror("malloc failed");
return 1;
}
// 2. 使用柔性数组
fb->len = n;
for (int i = 0; i < n; i++) {
fb->data[i] = i * 10;
}
// 3. 打印
printf("柔性数组内容:\n");
for (int i = 0; i < fb->len; i++) {
printf("%d ", fb->data[i]);
}
printf("\n");
// 4. 释放
free(fb);
return 0;
}
运行输出:
plaintext
柔性数组内容:
0 10 20 30 40
柔性数组 vs 指针方式(对比代码)
指针方式(不推荐)
c
struct PtrBuf {
int len;
int *data;
};
struct PtrBuf *pb = malloc(sizeof(struct PtrBuf));
pb->data = malloc(5 * sizeof(int));
需要:
- 两次 malloc
- 两次 free
- 内存不连续
- 指针占用额外空间
柔性数组(推荐)
c
struct FlexBuf *fb = malloc(sizeof(struct FlexBuf) + 5 * sizeof(int));
只需:
- 一次 malloc
- 一次 free
- 内存连续
- 不占指针空间
柔性数组实际应用示例:动态字符串缓冲区
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct DynamicStr {
int len;
char str[];
};
int main() {
const char *msg = "hello flexible array";
int len = strlen(msg);
struct DynamicStr *ds = malloc(sizeof(struct DynamicStr) + (len + 1));
ds->len = len;
strcpy(ds->str, msg);
printf("string: %s\n", ds->str);
printf("length: %d\n", ds->len);
free(ds);
return 0;
}
运行输出:
plaintext
string: hello flexible array
length: 20
四、柔性数组的注意事项(非常重要)
- 柔性数组成员必须是结构体最后一个成员
- 不能在结构体里定义多个柔性数组
- 不能用 sizeof 获取数组大小
- 不能静态分配,必须用 malloc/realloc
- 柔性数组不能直接拷贝结构体(会越界)