You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,提问作者נירייב שמואל

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:50:51