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

如何在另一个函数中修改char**?C语言字符串数组赋值错误排查

问题分析与修复方案

错误根源

你的代码里,func函数循环内的char buf[10];是栈上的局部变量。整个for循环中,buf复用的是同一块栈内存地址——每次循环调用snprintf都会把新内容写入这块内存,然后将该地址赋值给s[i]。当func执行完毕返回main时,栈上的buf内存会被操作系统回收,此时s数组的三个指针都指向同一块已经失效的内存区域。而这块内存最后一次被写入的内容是#2,所以main中打印时三个指针输出的都是这个值。

修复方案

以下是两种实用的修复方式:

方式1:动态分配堆内存

通过malloc在堆上分配内存,堆内存不会随函数返回而释放,注意使用完后要手动释放避免内存泄漏:

#include <stdio.h>
#include <stdlib.h>

void func(char **s){
    for(int i=0; i<3; i++){
        char *buf = malloc(10);
        if (!buf) { // 检查内存分配是否成功
            perror("malloc failed");
            exit(EXIT_FAILURE);
        }
        snprintf(buf, 10, "#%d", i);
        s[i] = buf;
    }
}

int main()
{
    char *s[3];
    func(s);
    for(int i=0; i<3; i++){
        printf("%s ", s[i]);
    }
    // 释放堆内存
    for(int i=0; i<3; i++){
        free(s[i]);
    }
    return 0;
}

方式2:预先分配栈缓冲区

在main中提前分配好足够的缓冲区,传递给func使用,缓冲区的生命周期覆盖整个打印过程:

#include <stdio.h>

void func(char **s, char bufs[3][10]){
    for(int i=0; i<3; i++){
        snprintf(bufs[i], 10, "#%d", i);
        s[i] = bufs[i];
    }
}

int main()
{
    char *s[3];
    char bufs[3][10]; // 预先分配3个长度为10的栈缓冲区
    func(s, bufs);
    for(int i=0; i<3; i++){
        printf("%s ", s[i]);
    }
    return 0;
}

补充:静态缓冲区方案(谨慎使用)

如果不想用动态分配或提前传缓冲区,可以使用静态存储区的缓冲区数组,但静态内存是全局共享的,多次调用func会覆盖之前的数据,仅适合一次性场景:

#include <stdio.h>

void func(char **s){
    static char bufs[3][10];
    for(int i=0; i<3; i++){
        snprintf(bufs[i], 10, "#%d", i);
        s[i] = bufs[i];
    }
}

int main()
{
    char *s[3];
    func(s);
    for(int i=0; i<3; i++){
        printf("%s ", s[i]);
    }
    return 0;
}

内容的提问来源于stack exchange,提问作者Unyaya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 12:35:18