如何在C函数内实现更优的动态内存分配?现有代码求改进
C语言动态数组优化方案(针对Token收集场景)
核心改进:封装动态数组结构体
你反感用输出参数返回长度的点非常合理——C语言没有原生容器,但我们可以自己封装一个类似vector的结构体,把数组指针、元素数量、容量打包在一起,彻底摆脱输出参数的尴尬。
先定义专用的Token数组结构体:
#include <stdlib.h> // 假设你已定义Token相关类型 typedef enum { TOKEN_EOF, /* 其他Token类型 */ } TokenType; typedef struct { TokenType type; /* Token的其他字段 */ } Token; typedef struct { Token* data; int count; int capacity; } TokenArray; // 假设你的错误终止函数已实现 void die(const char* msg);
重构Lexer_Run函数
基于上面的结构体,重构后的代码逻辑更简洁,完全不需要输出参数:
TokenArray Lexer_Run(Lexer* lexer) { TokenArray arr = {0}; // 初始容量设为128,和你的原逻辑一致 arr.capacity = 128; arr.data = malloc(arr.capacity * sizeof(Token)); if (!arr.data) die("Memory allocation failed!"); Token token; // 把Token获取直接写进循环条件,消除冗余的前置调用 while ((token = Lexer_Advance(lexer)).type != TOKEN_EOF) { // 扩容判断:元素数等于容量时再扩容,原代码的size-1是多余的浪费 if (arr.count >= arr.capacity) { int new_cap = arr.capacity * 2; Token* new_data = realloc(arr.data, new_cap * sizeof(Token)); if (!new_data) die("Memory allocation failed!"); arr.data = new_data; arr.capacity = new_cap; } arr.data[arr.count++] = token; } // 可选缩容:如果不是内存极度紧张,建议去掉这一步——减少一次内存分配操作 // Token* trimmed = realloc(arr.data, arr.count * sizeof(Token)); // if (trimmed) { arr.data = trimmed; arr.capacity = arr.count; } return arr; }
额外细节优化
- 去掉强制类型转换:C语言中
malloc/realloc返回void*,可以直接赋值给Token*,强制转换不仅多余,还可能在忘记包含<stdlib.h>时隐藏编译错误(此时malloc会被默认当作返回int的函数,强制转换会掩盖类型不匹配问题)。 - 简化循环逻辑:原代码先调用一次
Lexer_Advance再进入循环,重构后直接把获取Token的操作放进while条件,消除冗余代码,逻辑更连贯。 - 扩容策略可选调整:如果担心2倍扩容导致的内存碎片,可以改成1.5倍扩容(比如
new_cap = arr.capacity + arr.capacity / 2),平衡扩容效率和内存利用率。
使用示例
调用方现在可以像用vector一样直接操作:
// 初始化词法分析器 Lexer lexer = {/* 填充初始化数据 */}; TokenArray tokens = Lexer_Run(&lexer); // 遍历处理Token for (int i = 0; i < tokens.count; i++) { // 处理tokens.data[i] } // 用完后记得释放内存 free(tokens.data);
内容的提问来源于stack exchange,提问作者KilakOriginal
相关产品推荐
相关产品推荐

