C语言拼接两个字符串:不使用malloc()实现concat()函数
无malloc实现C语言字符串拼接函数concat()
嘿,我来帮你搞定这个不用malloc()的字符串拼接问题!先聊聊你原来的代码,虽然能运行,但有几个小坑:比如拼写错了length写成lengh,最重要的是没加字符串终止符'\0',这会导致返回的字符串是无效的;而且固定malloc(15)太局限,字符串总长度超过15就会溢出。
言归正传,不用动态内存分配的话,有几种靠谱的方案,我一个个给你拆解:
方案1:使用静态字符缓冲区
这种方法是在函数内部定义一个静态的字符数组来存结果,优点是调用简单,但缺点也很明显:
char* concat(const char *s1, const char *s2) { size_t len1 = simple_strlen(s1); size_t len2 = simple_strlen(s2); // 定义一个足够大的静态缓冲区(根据你的需求调整大小) static char result[1024]; size_t i = 0; // 复制第一个字符串 while (i < len1) { result[i] = s1[i]; i++; } // 复制第二个字符串 size_t j = 0; while (j < len2) { result[i + j] = s2[j]; j++; } // 必须加终止符!这是字符串的灵魂 result[i + j] = '\0'; return result; }
注意事项:
- 静态缓冲区大小固定,如果两个字符串总长度超过缓冲区大小,会触发缓冲区溢出,非常危险;
- 静态内存是全局共享的,多线程并发调用或者多次连续调用会覆盖之前的结果;
- 返回的指针指向静态内存,绝对不能用
free()去释放它。
方案2:让调用者提供目标缓冲区(最推荐)
这是工业界最常用的安全方案,把内存管理的责任交给调用者,灵活又避免了静态缓冲区的问题:
// 返回目标缓冲区指针,方便链式调用;也可以返回bool表示是否成功 char* concat(char *dest, const char *s1, const char *s2) { if (dest == NULL) return NULL; size_t len1 = simple_strlen(s1); size_t len2 = simple_strlen(s2); size_t i = 0; // 复制s1到目标缓冲区 while (i < len1) { dest[i] = s1[i]; i++; } // 复制s2到目标缓冲区的后半段 size_t j = 0; while (j < len2) { dest[i + j] = s2[j]; j++; } dest[i + j] = '\0'; return dest; }
调用示例:
// 调用者自己分配缓冲区,大小要足够存下两个字符串+终止符 char buf[256]; concat(buf, "Hello, ", "World!"); printf("%s\n", buf); // 输出:Hello, World!
优势:
- 内存由调用者控制,可大可小,完全避免溢出风险(只要调用者计算好大小);
- 线程安全,每个调用者的缓冲区独立;
- 不需要担心内存泄漏,因为没有动态分配。
方案3:使用C99变长数组(VLA)
如果你用的是支持C99及以后的编译器,可以用变长数组,但要注意栈空间有限,不适合超大字符串:
// 函数接收调用者提供的变长缓冲区,以及缓冲区大小 void concat(char *dest, size_t dest_size, const char *s1, const char *s2) { if (dest == NULL || dest_size == 0) return; size_t len1 = simple_strlen(s1); size_t len2 = simple_strlen(s2); // 先检查缓冲区是否足够,不够的话直接清空返回 if (len1 + len2 + 1 > dest_size) { dest[0] = '\0'; return; } size_t i = 0; while (i < len1) { dest[i] = s1[i]; i++; } size_t j = 0; while (j < len2) { dest[i + j] = s2[j]; j++; } dest[i + j] = '\0'; }
调用示例:
const char *str1 = "I love "; const char *str2 = "C programming"; // 用变长数组刚好匹配需要的大小 char buf[simple_strlen(str1) + simple_strlen(str2) + 1]; concat(buf, sizeof(buf), str1, str2); printf("%s\n", buf); // 输出:I love C programming
注意事项:
- VLA在栈上分配,栈空间通常只有几MB,超大字符串会导致栈溢出;
- 只有C99及以后的标准支持VLA,某些编译器(比如MSVC)可能不支持。
最后再提一下你原来代码的优化点:
- 把
lengh改成正确的length; - 一定要添加字符串终止符
'\0',否则拼接后的字符串无法被标准库函数正确识别; - 原来的嵌套循环可以拆成两个独立的循环,代码更清晰。
内容的提问来源于stack exchange,提问作者נירייב שמואל
相关产品推荐
相关产品推荐

