C语言的“动态数组”和“变长数组”
掩码结构体宏的实现本质上就是使用一个掩码数组 chMask 把结构体保护起来。见《大佬的PLOOC使用示例及其基于C语言的面向对象编程-傻孩子.pdf》
1 /* 公众号:嵌入式大杂烩 */ 2 #ifndef __DYNAMIC_ARRAY_H 3 #define __DYNAMIC_ARRAY_H 4 5 /* 结构体“重命名” */ 6 typedefstruct dynamic_array dynamic_array_def; 7 8 /* 初始化dynamic_array */ 9 dynamic_array_def *DA_Init(void); 10 11 /* 销毁dynamic_array */ 12 voidDA_Clean(dynamic_array_def *pThis); 13 14 /* 设置dynamic_array长度 */ 15 voidDA_SetSize(dynamic_array_def *pThis, unsigned len); 16 17 /* 获取dynamic_array长度 */ 18 unsignedDA_GetSize(dynamic_array_def *pThis); 19 20 /* 设置dynamic_array某元素的值 */ 21 intDA_SetValue(dynamic_array_def *pThis, unsigned index, int value); 22 23 /* 获取dynamic_array某元素的值 */ 24 intDA_GetValue(dynamic_array_def *pThis, unsigned index, int *pValue); 25 26 #endif
1 /* 公众号:嵌入式大杂烩 */ 2 #include "dynamic_array.h" 3 #include <stdlib.h> 4 5 /* 创建一个动态数组结构体模板 */ 6 struct dynamic_array 7 { 8 int*array; 9 unsigned len; 10 }; 11 12 /* 初始化dynamic_array */ 13 dynamic_array_def *DA_Init(void) 14 { 15 dynamic_array_def *pArray =malloc(sizeof(dynamic_array_def)); 16 17 pArray->array=NULL; 18 pArray->len =0; 19 } 20 21 /* 销毁dynamic_array */ 22 voidDA_Clean(dynamic_array_def *pThis) 23 { 24 free(pThis->array); 25 pThis->len =0; 26 free(pThis); 27 } 28 29 /* 设置dynamic_array长度 */ 30 voidDA_SetSize(dynamic_array_def *pThis, size_t len) 31 { 32 pThis->len = len; 33 pThis->array=(int*)realloc(pThis->array, pThis->len*sizeof(int)); 34 } 35 36 /* 获取dynamic_array长度 */ 37 size_tDA_GetSize(dynamic_array_def *pThis) 38 { 39 return pThis->len; 40 } 41 42 /* 设置dynamic_array某元素的值 */ 43 intDA_SetValue(dynamic_array_def *pThis, size_t index, int value) 44 { 45 if(index > pThis->len) 46 { 47 return-1; 48 } 49 50 pThis->array[index]= value; 51 return0; 52 } 53 54 /* 获取dynamic_array某元素的值 */ 55 intDA_GetValue(dynamic_array_def *pThis, size_t index, int *pValue) 56 { 57 if(index > pThis->len) 58 { 59 return-1; 60 } 61 62 *pValue = pThis->array[index]; 63 return0; 64 }
变长数组VLA(数组的长度由变量确定):
为何要引入VLA:定长数组使用方便, 但是却浪费空间; 指针形式【动态数组】只多使用了一个指针的空间, 不会造成大量空间分浪费, 但是使用起来需要多次分配, 多次释放,忘记释放就会内存泄漏。
变长数组是 C99 标准新增的特性,它允许数组的长度不是固定的编译时常量,而是根据程序运行时的变量或表达式来决定,特别适合需要动态大小的局部数组[如数据包长度不定的解析函数中,局部变量数组】场景。注意:需要检查数组的长度不能为0或负数。
在标准的C/C++中不允许0长度数组,而在GNU C中可以(是GNU的扩展。C99之间 定义时长度为arry[0];C99或之后可以留空arry[]).变成数组可以节约空间,解决使用数组时内存的冗余和数组的越界问题。但也有一个缺点就是结构体中的变长数组【只能放在结构体的最后面】。
1 typedef struct { 2 int len; 3 //int array[];/*!!!变长数组只能放在结构体的最后面*/ 4 int CRC; 5 int array[0];/*C99为int array[]*/ 6 }SoftArray;
1 #include <stdio.h> 2 void sum_array(int size) { 3 int arr[size]; // 变长数组,调用时确定 4 for (int i = 0; i < size; i++) { 5 arr[i] = i * 2; 6 } 7 int sum = 0; 8 for (int i = 0; i < size; i++) { 9 sum += arr[i]; 10 } 11 printf("数组元素之和:%d\n", sum); 12 } 13 int main() { 14 int n; 15 printf("请输入数组大小:"); 16 scanf("%d", &n); 17 sum_array(n); 18 return 0; 19 }
1) 优点
- 简单易用:无需手动分配和释放内存。
- 局部优化:栈上分配通常比堆上分配更快。
- 动态性:无需提前知道固定大小。
2) 局限性
- 栈空间限制:栈大小有限(通常几 MB),过大的变长数组会导致栈溢出。
- 仅限局部:不能声明为全局变量或静态变量。
- 兼容性:C11 将 VLA 设为可选特性,部分编译器可能不支持。
注意事项
- 大小检查:确保长度不为负数或零,避免未定义行为。
- 栈溢出:避免声明过大的变长数组,例如
int arr[1000000]可能崩溃。 - 编译器支持:使用前确认编译器支持 C99 或更高版本(如 gcc 使用
-std=c99)
浙公网安备 33010602011771号