C语言中的柔性数组

发布时间:2026/8/14 6:19:13
C语言中的柔性数组 C语言中为了实现变长结构体引入了柔性数组既省内存又比指针方案更高效更安全。本文将主要来认识柔性数组。一、柔性数组的定义C99中结构中的最后一个元素可以是一个大小为0数组这个数组就是柔性数组。定义方式如下structstruct_arr{inta;intb[];//柔性数组成员,有的编译器要求写成 int b[0]};柔性数组“int b[]”还是“int b[0]”主要看编译器有的编译器两种都支持。上面的数组名b代表一个地址标签类似struct这个标签是整个结构体的延伸部分的一个别名不占据存储空间。如果把b[]处换为“int *b”对于指针b需要为它开辟一个8字节的空间前提64位的操作系统。两者的差距可参考下面实际运行结果#includestdio.h#includewindows.h#includemath.hstructstruct_arr0{inta;intb[];};structstruct_arr1{intc;int*d;};intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);structstruct_arr0sa0;structstruct_arr1sa1;printf(struct_arr0结构体大小%zu字节\n,sizeof(sa0));printf(struct_arr1结构体大小%zu字节\n,sizeof(sa1));return0;}运行结果如下对比项柔性数组指针申请/释放次数一次malloc一次free要两次malloc/free内存情况内存连续访问更快CPU缓存友好序列化/网络传输方便数据和结构体不连续缓存不友好潜在风险不会泄漏容易内存泄漏、野指针缺点数组长度分配以后不能动态改变可以后期重新realloc改变数据长度二、柔性数组的使用如上面的b[],在a后面就是b后面我们可以使用malloc申请一段任意大小的空间用b去访问那段空间即操作灵活同一个类型的结构体指针可以操作的空间大小可变#includestdio.h#includewindows.h#includemath.hstructstruct_arr0{inta;intb[];};structstruct_arr1{intc;int*d;};intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);structstruct_arr0*sa1malloc(sizeof(structstruct_arr0)2*sizeof(int));//此时b的空间大小就是8字节sa1-a1000;*(sa1-b)5;*(sa1-b1)100;printf(柔性数组\n);printf(结构体-柔性数组中a:%d\n,sa1-a);printf(结构体-柔性数组中b[0]里存储的是%d\n,*(sa1-b));printf(结构体-柔性数组中b[1]里存储的是%d\n,*(sa1-b1));printf(sa1结构体的首地址是%p\n,(void*)sa1);printf(结构体-柔性数组中a地址的是%p\n,(void*)(sa1-a));printf(结构体-柔性数组中b地址的是%p\n,(void*)sa1-b[0]);printf(结构体-柔性数组中b[1]里地址的是%p\n,(void*)sa1-b[1]);structstruct_arr1*sa2malloc(sizeof(structstruct_arr1));//第一次malloc结构体本身sa2-dmalloc(2*sizeof(int));//第二次mallocd指向独立内存sa2-c2000;sa2-d[0]8;sa2-d[1]300;printf(指针版本\n);printf(结构体-指针中c:%d\n,sa2-c);printf(结构体-指针中d[0]里存储的是%d\n,sa2-d[0]);printf(结构体-指针中d[1]里存储的是%d\n,sa2-d[1]);printf(sa2结构体的首地址是%p\n,(void*)sa2);printf(结构体-指针中c地址的是%p\n,(void*)(sa2-c));printf(结构体-指针中d的地址的是%p\n,(void*)sa2-d);printf(结构体-指针中d[0]内容的地址的是%p\n,(void*)sa2-d[0]);printf(结构体-指针中d[1]内容的地址的是%p\n,(void*)sa2-d[1]);free(sa1);free(sa2-d);free(sa2);return0;}运行结果sa1-b:b[0]、b[1]全部来自一次malloc释放freesa1即可只free一次sa2-d:仅存一个地址d指向另外一个malloc出来的独立堆块需要malloc2次释放要先freesa2-d),再free(sa2),忘记释放d直接free(sa2)直接内存泄漏二、柔性数组的注意事项1、柔性数组成员必须放在结构体最后三、对比其他语言柔性数组只有C、C有在嵌入式、底层开发场景使用C:不推荐柔性数组用std:vectorJava没有柔性数组用List、动态数组python/go:自带动态数组不需要这种语法总之柔性数组是C语言为了高效处理“变长结构体”而设计的特性