C语言字符串间字符赋值失败:剥离$格式符时目标字符串无内容问题
现有代码的核心问题
- 野指针访问:
point指针没有初始化,也没有申请对应的内存空间,直接执行*point++ = *str++属于未定义行为,轻则写入无效内存拿不到结果,重则直接触发程序崩溃。 - 死循环逻辑:当遍历到
$字符时,没有进入*str != '$'的分支,str指针不会向后移动,循环会一直卡在当前位置永远不会退出。 - 结果无法导出:函数返回值为
void,处理后的内容没有任何方式传递给外部调用方使用,自然没法完成赋值操作。 - 缺少字符串结束符:就算前面的问题都解决,遍历结束后没有给结果字符串追加
\0结束标记,得到的不是合法的C语言字符串。
修复方案
推荐采用调用方传入缓冲区的实现方式,更适配Rom代码库的传统风格,避免堆内存分配忘记释放导致的内存泄漏问题,修复后代码示例如下:
// 新增参数buf为调用方传入的缓冲区,buf_len为缓冲区大小 void act_new(const char *format, char *buf, int buf_len) { const char *str; char *point; str = format; point = buf; // point绑定到传入的缓冲区上 while ( *str != '\0' && (point - buf) < buf_len - 1) { // 避免缓冲区溢出 if ( *str != '$' ) { *point++ = *str++; continue; } // 遇到$符号,跳过$和后面紧跟的一个字符 str++; if (*str != '\0') { str++; } } *point = '\0'; // 追加字符串结束符 }
调用方式示例:
char result[64]; // 提前声明缓冲区 act_new("$t does $d", result, sizeof(result)); // 此时result里就是预期的" does "字符串
如果你希望函数直接返回处理后的字符串,也可以修改为堆内存分配的版本,使用的时候记得用完调用free()释放即可:
char* act_new(const char *format) { int len = strlen(format); char *buf = malloc(len + 1); // 最坏情况没有$符,长度和原串一致 if (!buf) { return NULL; } const char *str = format; char *point = buf; while ( *str != '\0' ) { if ( *str != '$' ) { *point++ = *str++; continue; } str++; if (*str != '\0') { str++; } } *point = '\0'; return buf; }
调用方式示例:
char *result = act_new("$t does $d"); // 后续使用result free(result); // 用完必须释放
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

